diff --git a/.gitignore b/.gitignore index fe26786..a547bf3 100644 --- a/.gitignore +++ b/.gitignore @@ -11,7 +11,7 @@ node_modules dist dist-ssr *.local -.env + # Editor directories and files .vscode/* !.vscode/extensions.json @@ -21,4 +21,4 @@ dist-ssr *.ntvs* *.njsproj *.sln -*.sw? \ No newline at end of file +*.sw? diff --git a/client/.dockerignore b/client/.dockerignore new file mode 100644 index 0000000..3f29ae6 --- /dev/null +++ b/client/.dockerignore @@ -0,0 +1,4 @@ +node_modules +dist +.git +.env diff --git a/client/.env b/client/.env new file mode 100644 index 0000000..f748922 --- /dev/null +++ b/client/.env @@ -0,0 +1,4 @@ +VITE_SERVER_ENDPOINT = http://51.20.77.21:3000/api +VITE_TOKEN_KEY = thinkify +VITE_USER_ROLE = role +VITE_COOKIE_EXPIRES = 1 diff --git a/client/Dockerfile b/client/Dockerfile new file mode 100644 index 0000000..c759771 --- /dev/null +++ b/client/Dockerfile @@ -0,0 +1,31 @@ +# ---- Build Stage ---- +FROM node:20-alpine AS build + +WORKDIR /app + +COPY package.json . +RUN npm install + +COPY . . + +ARG VITE_SERVER_ENDPOINT +ARG VITE_TOKEN_KEY +ARG VITE_USER_ROLE +ARG VITE_COOKIE_EXPIRES + +ENV VITE_SERVER_ENDPOINT=$VITE_SERVER_ENDPOINT +ENV VITE_TOKEN_KEY=$VITE_TOKEN_KEY +ENV VITE_USER_ROLE=$VITE_USER_ROLE +ENV VITE_COOKIE_EXPIRES=$VITE_COOKIE_EXPIRES + +RUN npm run build + +# ---- Serve Stage ---- +FROM nginx:1.25-alpine + +COPY --from=build /app/dist /usr/share/nginx/html +COPY nginx.conf /etc/nginx/conf.d/default.conf + +EXPOSE 80 + +CMD ["nginx", "-g", "daemon off;"] diff --git a/client/nginx.conf b/client/nginx.conf new file mode 100644 index 0000000..258cbf6 --- /dev/null +++ b/client/nginx.conf @@ -0,0 +1,29 @@ +server { + listen 80; + server_name _; + + root /usr/share/nginx/html; + index index.html; + + # Docker's internal DNS resolver — forces nginx to re-resolve at runtime + resolver 127.0.0.11 valid=10s; + + # Proxy all /api requests to the Express backend + location /api { + set $upstream http://server:3000; + proxy_pass $upstream; + proxy_http_version 1.1; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header Cookie $http_cookie; + } + + # React Router fallback + location / { + try_files $uri $uri/ /index.html; + } + + gzip on; + gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript; +} diff --git a/client/package-lock.json b/client/package-lock.json index 97290ce..909d9ed 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -98,7 +98,6 @@ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.4.tgz", "integrity": "sha512-MBVlMXP+kkl5394RBLSxxk/iLTeVGuXTV3cIDXavPpMMqnSnt6apKgan/U8O3USWZCWZT/TbgfEpKa4uMgN4Dg==", "dev": true, - "peer": true, "dependencies": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.24.2", @@ -474,7 +473,6 @@ "version": "11.11.4", "resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.11.4.tgz", "integrity": "sha512-t8AjMlF0gHpvvxk5mAtCqR4vmxiGHCeJBaQO6gncUSdklELOgtwjerNY2yuJNfwnc6vi16U/+uMF+afIawJ9iw==", - "peer": true, "dependencies": { "@babel/runtime": "^7.18.3", "@emotion/babel-plugin": "^11.11.0", @@ -515,7 +513,6 @@ "version": "11.11.5", "resolved": "https://registry.npmjs.org/@emotion/styled/-/styled-11.11.5.tgz", "integrity": "sha512-/ZjjnaNKvuMPxcIiUkf/9SHoG4Q196DRl1w82hQ3WCsjo1IUR8uaGWrC6a87CrYAW0Kb/pK7hk8BnLgLRi9KoQ==", - "peer": true, "dependencies": { "@babel/runtime": "^7.18.3", "@emotion/babel-plugin": "^11.11.0", @@ -1188,7 +1185,6 @@ "version": "5.15.15", "resolved": "https://registry.npmjs.org/@mui/material/-/material-5.15.15.tgz", "integrity": "sha512-3zvWayJ+E1kzoIsvwyEvkTUKVKt1AjchFFns+JtluHCuvxgKcLSRJTADw37k0doaRtVAsyh8bz9Afqzv+KYrIA==", - "peer": true, "dependencies": { "@babel/runtime": "^7.23.9", "@mui/base": "5.0.0-beta.40", @@ -1838,7 +1834,6 @@ "version": "18.2.74", "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.74.tgz", "integrity": "sha512-9AEqNZZyBx8OdZpxzQlaFEVCSFUM2YXJH46yPOiOpm078k6ZLOCcuAzGum/zK8YBwY+dbahVNbHrbgrAwIRlqw==", - "peer": true, "dependencies": { "@types/prop-types": "*", "csstype": "^3.0.2" @@ -1899,7 +1894,6 @@ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", "dev": true, - "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -2203,7 +2197,6 @@ "url": "https://github.com/sponsors/ai" } ], - "peer": true, "dependencies": { "caniuse-lite": "^1.0.30001587", "electron-to-chromium": "^1.4.668", @@ -2555,8 +2548,7 @@ "node_modules/dayjs": { "version": "1.11.11", "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.11.tgz", - "integrity": "sha512-okzr3f11N6WuqYtZSvm+F776mB41wRZMhKP+hc34YdW+KmtYYK9iqvHSwo2k9FEH3fhGXvOPV6yz2IcSrfRUDg==", - "peer": true + "integrity": "sha512-okzr3f11N6WuqYtZSvm+F776mB41wRZMhKP+hc34YdW+KmtYYK9iqvHSwo2k9FEH3fhGXvOPV6yz2IcSrfRUDg==" }, "node_modules/debug": { "version": "4.3.4", @@ -2920,7 +2912,6 @@ "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz", "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==", "dev": true, - "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", @@ -4705,7 +4696,6 @@ "version": "18.2.0", "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz", "integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==", - "peer": true, "dependencies": { "loose-envify": "^1.1.0" }, @@ -4754,7 +4744,6 @@ "version": "18.2.0", "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz", "integrity": "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==", - "peer": true, "dependencies": { "loose-envify": "^1.1.0", "scheduler": "^0.23.0" @@ -4767,7 +4756,6 @@ "version": "7.51.2", "resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.51.2.tgz", "integrity": "sha512-y++lwaWjtzDt/XNnyGDQy6goHskFualmDlf+jzEZvjvz6KWDf7EboL7pUvRCzPTJd0EOPpdekYaQLEvvG6m6HA==", - "peer": true, "engines": { "node": ">=12.22.0" }, @@ -5583,7 +5571,6 @@ "resolved": "https://registry.npmjs.org/vite/-/vite-5.2.8.tgz", "integrity": "sha512-OyZR+c1CE8yeHw5V5t59aXsUPPVTHMDjEZz8MgguLL/Q7NblxhZUlTu9xSPqlsUO/y+X7dlU05jdhvyycD55DA==", "dev": true, - "peer": true, "dependencies": { "esbuild": "^0.20.1", "postcss": "^8.4.38", diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..79cd9d0 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,63 @@ +version: '3.8' + +services: + + mongodb: + image: mongo:7 + container_name: thinkify-mongodb + restart: unless-stopped + volumes: + - mongo_data:/data/db + networks: + - thinkify-net + + server: + build: + context: ./server + dockerfile: Dockerfile + container_name: thinkify-server + restart: unless-stopped + ports: + - "3000:3000" + environment: + PORT: 3000 + DATABASE_URL: mongodb://mongodb:27017/ + DATABASE_NAME: thinkify + BCRYPT_GEN_SALT_NUMBER: 10 + JWT_SECRET_KEY: thinkify_super_secret_jwt_key_2024 + COOKIE_EXPIRES: 5d + COOKIE_KEY: thinkify + UPLOAD_DIRECTORY: uploads + CLIENT_ORIGIN: http://51.20.77.21 + volumes: + - uploads_data:/app/uploads + depends_on: + - mongodb + networks: + - thinkify-net + + client: + build: + context: ./client + dockerfile: Dockerfile + args: + VITE_SERVER_ENDPOINT: http://51.20.77.21/api + VITE_TOKEN_KEY: thinkify + VITE_USER_ROLE: role + VITE_COOKIE_EXPIRES: 1 + container_name: thinkify-client + restart: unless-stopped + ports: + - "80:80" + depends_on: + - server + networks: + - thinkify-net + +volumes: + mongo_data: + uploads_data: + +networks: + thinkify-net: + driver: bridge diff --git a/k8s/apply.sh b/k8s/apply.sh new file mode 100755 index 0000000..1cff444 --- /dev/null +++ b/k8s/apply.sh @@ -0,0 +1,46 @@ +#!/bin/bash +set -e + +echo "==> Namespace" +kubectl apply -f namespace.yml + +echo "==> ConfigMap" +kubectl apply -f config-map.yml + +echo "==> Secret" +kubectl apply -f secret.yml + +echo "==> MongoDB Service (Headless)" +kubectl apply -f mongodb-service.yml + +echo "==> MongoDB StatefulSet" +kubectl apply -f mongodb-statfulset.yml + +echo "==> Waiting for MongoDB..." +kubectl rollout status statefulset/mongodb -n thinkify --timeout=120s + +echo "==> PVC" +kubectl apply -f pvc.yml + +echo "==> Server Deployment" +kubectl apply -f server-deployment.yml + +echo "==> Server Service" +kubectl apply -f server-service.yml + +echo "==> Waiting for Server..." +kubectl rollout status deployment/server -n thinkify --timeout=60s + +echo "==> Client Deployment" +kubectl apply -f client-deployment.yml + +echo "==> Client Service" +kubectl apply -f client-service.yml + +echo "==> Ingress" +kubectl apply -f ingress.yml + +echo "" +echo "Done. App: http://51.20.77.21" +echo "Pods: kubectl get pods -n thinkify" +echo "Ingress: kubectl get ingress -n thinkify" diff --git a/k8s/client-deployment.yml b/k8s/client-deployment.yml new file mode 100644 index 0000000..026bc6e --- /dev/null +++ b/k8s/client-deployment.yml @@ -0,0 +1,36 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: client + namespace: thinkify + labels: + app: client +spec: + replicas: 1 + selector: + matchLabels: + app: client + template: + metadata: + labels: + app: client + spec: + containers: + - name: client + image: manthan010/thinkify-client:latest + imagePullPolicy: IfNotPresent + ports: + - containerPort: 80 + resources: + requests: + memory: "64Mi" + cpu: "50m" + limits: + memory: "128Mi" + cpu: "200m" + readinessProbe: + httpGet: + path: / + port: 80 + initialDelaySeconds: 5 + periodSeconds: 5 diff --git a/k8s/client-service.yml b/k8s/client-service.yml new file mode 100644 index 0000000..89c0582 --- /dev/null +++ b/k8s/client-service.yml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: Service +metadata: + name: client + namespace: thinkify + labels: + app: client +spec: + type: ClusterIP + selector: + app: client + ports: + - name: http + port: 80 + targetPort: 80 diff --git a/k8s/config-map.yml b/k8s/config-map.yml new file mode 100644 index 0000000..bd124b2 --- /dev/null +++ b/k8s/config-map.yml @@ -0,0 +1,13 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: thinkify-config + namespace: thinkify +data: + PORT: "3000" + DATABASE_NAME: "thinkify" + BCRYPT_GEN_SALT_NUMBER: "10" + COOKIE_EXPIRES: "5d" + COOKIE_KEY: "thinkify" + UPLOAD_DIRECTORY: "uploads" + CLIENT_ORIGIN: "http://51.20.77.21" diff --git a/k8s/ingress.yml b/k8s/ingress.yml new file mode 100644 index 0000000..2a6ed21 --- /dev/null +++ b/k8s/ingress.yml @@ -0,0 +1,29 @@ +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: thinkify-ingress + namespace: thinkify + annotations: + nginx.ingress.kubernetes.io/proxy-read-timeout: "60" + nginx.ingress.kubernetes.io/proxy-connect-timeout: "10" +spec: + ingressClassName: nginx # change to "traefik" if using k3s default + rules: + - http: + paths: + # /api/* → Express backend directly (no rewrite needed, server handles /api prefix) + - path: /api + pathType: Prefix + backend: + service: + name: server-service + port: + number: 3000 + # /* → React frontend (nginx inside client handles SPA fallback) + - path: / + pathType: Prefix + backend: + service: + name: client + port: + number: 80 diff --git a/k8s/mongodb-clusterip-service.yml b/k8s/mongodb-clusterip-service.yml new file mode 100644 index 0000000..4528391 --- /dev/null +++ b/k8s/mongodb-clusterip-service.yml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: Service +metadata: + name: mongodb + namespace: thinkify + labels: + app: mongodb +spec: + type: ClusterIP + selector: + app: mongodb + ports: + - name: mongo + port: 27017 + targetPort: 27017 diff --git a/k8s/mongodb-service.yml b/k8s/mongodb-service.yml new file mode 100644 index 0000000..ff797e3 --- /dev/null +++ b/k8s/mongodb-service.yml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: Service +metadata: + name: mongodb-service + namespace: thinkify + labels: + app: mongodb +spec: + clusterIP: None + selector: + app: mongodb + ports: + - name: mongo + port: 27017 + targetPort: 27017 diff --git a/k8s/mongodb-statfulset.yml b/k8s/mongodb-statfulset.yml new file mode 100644 index 0000000..aef38a1 --- /dev/null +++ b/k8s/mongodb-statfulset.yml @@ -0,0 +1,62 @@ +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: mongodb-state + namespace: thinkify + labels: + app: mongodb +spec: + serviceName: mongodb-headless + replicas: 1 + selector: + matchLabels: + app: mongodb + template: + metadata: + labels: + app: mongodb + spec: + terminationGracePeriodSeconds: 30 + containers: + - name: mongodb + image: mongo:7 + ports: + - containerPort: 27017 + name: mongo + volumeMounts: + - name: mongo-data + mountPath: /data/db + resources: + requests: + memory: "256Mi" + cpu: "250m" + limits: + memory: "512Mi" + cpu: "500m" + livenessProbe: + exec: + command: + - mongosh + - --eval + - "db.adminCommand('ping')" + initialDelaySeconds: 30 + periodSeconds: 10 + timeoutSeconds: 5 + readinessProbe: + exec: + command: + - mongosh + - --eval + - "db.adminCommand('ping')" + initialDelaySeconds: 10 + periodSeconds: 5 + timeoutSeconds: 3 + volumeClaimTemplates: + - metadata: + name: mongo-data + spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 5Gi diff --git a/k8s/namespace.yml b/k8s/namespace.yml new file mode 100644 index 0000000..809a4c9 --- /dev/null +++ b/k8s/namespace.yml @@ -0,0 +1,4 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: thinkify diff --git a/k8s/pvc.yml b/k8s/pvc.yml new file mode 100644 index 0000000..08c8aaf --- /dev/null +++ b/k8s/pvc.yml @@ -0,0 +1,12 @@ +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: uploads-pvc + namespace: thinkify +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 2Gi + diff --git a/k8s/secret.yml b/k8s/secret.yml new file mode 100644 index 0000000..13147a5 --- /dev/null +++ b/k8s/secret.yml @@ -0,0 +1,9 @@ +apiVersion: v1 +kind: Secret +metadata: + name: thinkify-secret + namespace: thinkify +type: Opaque +stringData: + JWT_SECRET_KEY: "thinkify_super_secret_jwt_key_2024" + DATABASE_URL: "mongodb://mongodb:27017/" diff --git a/k8s/server-deployment.yml b/k8s/server-deployment.yml new file mode 100644 index 0000000..b27aafd --- /dev/null +++ b/k8s/server-deployment.yml @@ -0,0 +1,63 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: server-deployment + namespace: thinkify + labels: + app: server +spec: + replicas: 1 + selector: + matchLabels: + app: server + template: + metadata: + labels: + app: server + spec: + containers: + - name: server + image: manthan010/thinkify-server:latest + imagePullPolicy: IfNotPresent + ports: + - containerPort: 3000 + envFrom: + - configMapRef: + name: thinkify-config + env: + - name: JWT_SECRET_KEY + valueFrom: + secretKeyRef: + name: thinkify-secret + key: JWT_SECRET_KEY + - name: DATABASE_URL + valueFrom: + secretKeyRef: + name: thinkify-secret + key: DATABASE_URL + volumeMounts: + - name: uploads + mountPath: /app/uploads + resources: + requests: + memory: "128Mi" + cpu: "100m" + limits: + memory: "256Mi" + cpu: "500m" + readinessProbe: + httpGet: + path: / + port: 3000 + initialDelaySeconds: 10 + periodSeconds: 5 + livenessProbe: + httpGet: + path: / + port: 3000 + initialDelaySeconds: 20 + periodSeconds: 10 + volumes: + - name: uploads + persistentVolumeClaim: + claimName: uploads-pvc diff --git a/k8s/server-service.yml b/k8s/server-service.yml new file mode 100644 index 0000000..12a41ea --- /dev/null +++ b/k8s/server-service.yml @@ -0,0 +1,14 @@ +apiVersion: v1 +kind: Service +metadata: + name: server-service + namespace: thinkify + labels: + app: server +spec: + selector: + app: server + ports: + - name: http + port: 3000 + targetPort: 3000 diff --git a/nginx.conf.bck b/nginx.conf.bck new file mode 100644 index 0000000..42d71ad --- /dev/null +++ b/nginx.conf.bck @@ -0,0 +1,14 @@ +server { + listen 80; + server_name _; + + root /usr/share/nginx/html; + index index.html; + + location / { + try_files $uri $uri/ /index.html; + } + + gzip on; + gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript; +} diff --git a/server/.env b/server/.env new file mode 100644 index 0000000..1cd1fb1 --- /dev/null +++ b/server/.env @@ -0,0 +1,8 @@ +PORT = 3000 +DATABASE_URL = "mongodb+srv://mepey43052_db_user:Asd%40asd@mern.lrlau4v.mongodb.net/?appName=mernL" +DATABASE_NAME = thinkify +BCRYPT_GEN_SALT_NUMBER = 10 +JWT_SECRET_KEY = abcdefghijklmnopqrstuvwxyz +COOKIE_EXPIRES = 5d +COOKIE_KEY = thinkify +UPLOAD_DIRECTORY = uploads diff --git a/server/Dockerfile b/server/Dockerfile new file mode 100644 index 0000000..8771980 --- /dev/null +++ b/server/Dockerfile @@ -0,0 +1,14 @@ +FROM node:20-alpine + +WORKDIR /app + +COPY package.json . +RUN npm install + +COPY . . + +RUN mkdir -p uploads + +EXPOSE 3000 + +CMD ["node", "index.js"] diff --git a/server/controller/admin.js b/server/controller/admin.js index 0db0595..c85bdfe 100644 --- a/server/controller/admin.js +++ b/server/controller/admin.js @@ -1,4 +1,4 @@ -import bcrypt from 'bcrypt'; +import bcrypt from 'bcryptjs'; import { check, validationResult } from 'express-validator'; import jwt from 'jsonwebtoken'; @@ -128,4 +128,4 @@ const getRoleBasedUserCount = async (req, res) => { } } -export { login, getUserData, logOut, userList, getLastMonthNewUsersCount, getRoleBasedUserCount } \ No newline at end of file +export { login, getUserData, logOut, userList, getLastMonthNewUsersCount, getRoleBasedUserCount } diff --git a/server/controller/user.js b/server/controller/user.js index 6c6a654..27285ef 100644 --- a/server/controller/user.js +++ b/server/controller/user.js @@ -1,4 +1,4 @@ -import bcrypt from 'bcrypt'; +import bcrypt from 'bcryptjs'; import { check, validationResult } from 'express-validator'; import jwt from 'jsonwebtoken'; @@ -365,4 +365,4 @@ const removeUser = async (req, res) => { } -export { registration, login, getUserData, changePassword, getUsers, removeUser, getUserActivity } \ No newline at end of file +export { registration, login, getUserData, changePassword, getUsers, removeUser, getUserActivity } diff --git a/server/index.js b/server/index.js index 297a7cd..566c7a0 100644 --- a/server/index.js +++ b/server/index.js @@ -19,10 +19,12 @@ app.use( origin: [ "http://localhost:5173", "https://thinkify.vercel.app", + "http://51.20.77.21", ], credentials: true, }) ); + databaseConnection(DATABASE_URL, DATABASE_NAME); app.use(express.json()); app.use(cookieParser()); @@ -32,4 +34,4 @@ app.get("/", (req, res) => { res.send("Server Running Successfully"); }) -app.listen(PORT, () => { console.log(`Server Listening at http://localhost:${PORT}`) }); \ No newline at end of file +app.listen(PORT, () => { console.log(`Server Listening at http://localhost:${PORT}`) }); diff --git a/server/middleware/userAuthentication.js b/server/middleware/userAuthentication.js index 6f50a84..adf7601 100644 --- a/server/middleware/userAuthentication.js +++ b/server/middleware/userAuthentication.js @@ -1,40 +1,62 @@ -import jwt from 'jsonwebtoken'; -import { Types } from 'mongoose'; - +import jwt from "jsonwebtoken"; +import { Types } from "mongoose"; import UserModel from "../models/userSchema.js"; const userAuthentication = async (req, res, next) => { try { - const authorization = req.headers['authorization']; - if (authorization && authorization.startsWith("Bearer ")) { - const authorizationToken = authorization.split(" ")[1]; - if (authorizationToken && authorizationToken !== "null" && authorizationToken !== "undefined") { - const { userId } = jwt.verify(authorizationToken, process.env.JWT_SECRET_KEY) - if (Types.ObjectId.isValid(userId)) { - - const user = await UserModel.findById(userId).select("-password"); - if (user.role === "user") { - req.user = user - next(); - } else { - return res.status(403).json({ "status": false, "message": "Invalid Request" }); - } - - } else { - return res.status(403).json({ "status": false, "message": "Invalid Request" }); - } - - } else { - res.status(401).json({ "status": false, "message": "Authorization Failed" }); - } - } else { - throw new Error("Unauthorized User"); + const authorization = req.headers.authorization; + + if (!authorization || !authorization.startsWith("Bearer ")) { + return res.status(401).json({ + status: false, + message: "Unauthorized User", + }); + } + + const token = authorization.split(" ")[1]; + + if (!token || token === "null" || token === "undefined") { + return res.status(401).json({ + status: false, + message: "Authorization Failed", + }); + } + + const { userId } = jwt.verify(token, process.env.JWT_SECRET_KEY); + + if (!Types.ObjectId.isValid(userId)) { + return res.status(401).json({ + status: false, + message: "Invalid User ID", + }); + } + + const user = await UserModel.findById(userId).select("-password"); + + if (!user) { + return res.status(401).json({ + status: false, + message: "User not found", + }); } + if (user.role !== "user") { + return res.status(403).json({ + status: false, + message: "Invalid Request", + }); + } + + req.user = user; + next(); } catch (error) { - console.log(error) - res.status(500).json({ "status": false, "message": "Internal Server Error", "error": error }); + console.error(error); + + return res.status(401).json({ + status: false, + message: error.message, + }); } -} +}; -export default userAuthentication; \ No newline at end of file +export default userAuthentication; diff --git a/server/package.json b/server/package.json index 8af5cea..39145ae 100644 --- a/server/package.json +++ b/server/package.json @@ -11,7 +11,7 @@ "author": "", "license": "ISC", "dependencies": { - "bcrypt": "^5.1.1", + "bcryptjs": "^2.4.3", "cookie-parser": "^1.4.6", "cors": "^2.8.5", "dotenv": "^16.4.5",