নোড জেএস সার্ভারের জন্য একটি শক্তিশালী প্রমাণীকরণ সমাধান তৈরি করুন ডাটাবেস পরিচালনার জন্য Knex ব্যবহার করে, দক্ষ ক্যাশিংয়ের জন্য Redis এবং নির্বিঘ্ন রাউটিংয়ের জন্য এক্সপ্রেস। আমার Node.js অ্যাপ্লিকেশনগুলির জন্য একটি দ্রুত, স্বজ্ঞাত, এবং সুবিন্যস্ত প্রমাণীকরণ সমাধানের জন্য আমার অনুসন্ধানে, আমি কার্যকারিতার সাথে আপস না করে দ্রুত বাস্তবায়নের দাবিতে এমন পরিস্থিতির সম্মুখীন হয়েছি। ব্যবহারকারী সাইনআপ এবং লগইন থেকে শুরু করে ভুলে যাওয়া পাসওয়ার্ড পরিচালনা, ব্যবহারকারীর ডেটা আপডেট করা এবং এমনকি অ্যাকাউন্ট মুছে ফেলা পর্যন্ত, আমি একটি ব্যাপক সমাধান চেয়েছি যা এই প্রয়োজনীয় ব্যবহারকারীর মিথস্ক্রিয়াগুলির মাধ্যমে নির্বিঘ্নে নেভিগেট করে। এইভাবে, আমার নিবন্ধটির লক্ষ্য হল সুনির্দিষ্টভাবে উপস্থাপন করা - একটি সুসংহত পদ্ধতির মাধ্যমে প্রমাণীকরণ এবং ক্যাশিং বাস্তবায়নের জন্য সুস্পষ্ট পদ্ধতিগুলিকে একীভূত করা, একটি শক্তিশালী এবং দক্ষ ব্যবহারকারীর প্রবাহ নিশ্চিত করা। এখানে, আমরা মৌলিক ইনস্টলেশন পদ্ধতি এবং মডেল তৈরিকে বাইপাস করব, সরাসরি প্রমাণীকরণের জটিলতা এবং ব্যবহারকারীর প্রবাহের উপর নির্ভর করে। সেটআপের জন্য প্রয়োজনীয় সংস্থানগুলিতে নির্বিঘ্ন অ্যাক্সেস নিশ্চিত করে, আমরা নিবন্ধ জুড়ে কনফিগারেশন ফাইলগুলি পেতে সমস্ত প্রয়োজনীয় লিঙ্কগুলি অন্তর্ভুক্ত করব। টুলস এই বাস্তবায়নের জন্য, আমরা Knex, Express এবং Redis-এর পাশাপাশি Node.js সংস্করণ 20.11.1 ব্যবহার করব। উপরন্তু, আমরা আমাদের ডাটাবেস হিসাবে PostgreSQL ব্যবহার করব, যা নির্বিঘ্ন ব্যবস্থাপনার জন্য ডকার ব্যবহার করে কন্টেইনারাইজড এবং সাজানো হবে। আমাদের অ্যাপ্লিকেশনটির নাম হবে । আসুন সেই ফোল্ডারটি তৈরি করি এবং ভিতরে চালান বেসিক জেনারেট করতে user-flow-boilerplate npm init -y package.json { "name": "user-flow-boilerplate", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "keywords": [], "author": "", "license": "ISC" } প্রাথমিক package.json পরবর্তী ধাপ হল প্রয়োজনীয় নির্ভরতা যোগ করা: : নির্ভরতা npm i -S bcrypt body-parser cors dotenv express jsonwebtoken knex pg redis validator : dev নির্ভরতা npm i -D @babel/core @babel/eslint-parser @babel/plugin-transform-class-properties @babel/plugin-transform-runtime @babel/preset-env @babel/preset-typescript @faker-js/faker @types/bcrypt @types/body-parser @types/cors @types/express @types/jest @types/jsonwebtoken @types/node @types/node-cron @types/validator @typescript-eslint/eslint-plugin @typescript-eslint/parser babel-jest cross-env eslint eslint-config-prettier eslint-plugin-prettier jest nodemon npm-run-all prettier ts-jest ts-loader ts-node tsconfig-paths tslint typescript webpack webpack-cli webpack-node-externals এবং স্ক্রিপ্ট যোগ করুন যা আমাদের অ্যাপ্লিকেশন তৈরি এবং চালাবে: "scripts": { "start": "NODE_ENV=production node dist/bundle.js", "build": "NODE_ENV=production webpack --config webpack.config.js", "dev": "cross-env NODE_ENV=development && npm-run-all -p dev:*", "dev:build": "webpack --config webpack.config.js --watch", "dev:start": "nodemon --watch dist --exec node dist/bundle.js", "test": "NODE_ENV=test jest --config ./jest.config.js", "lint": "eslint ./src -c .eslintrc.json" }, আমাদের অ্যাপ্লিকেশনের সুচারু লঞ্চ নিশ্চিত করতে, একটি ফোল্ডার তৈরি করা এবং আমাদের প্রাথমিক এন্ট্রি পয়েন্ট ফাইল, , এটির মধ্যে স্থাপন করা অপরিহার্য। src index.ts require('dotenv').config(); import process from 'process'; import express from 'express'; import bodyParser from 'body-parser'; import cors from 'cors'; const app = express(); const PORT = process.env.PORT || 9999; app.use(bodyParser.json()); app.use(cors()); app.get('/api/v1/health', (req, res) => res.status(200).json({ message: 'OK' })); (async () => { try { app.listen(PORT, async () => { console.log(`Server is running on port ${PORT}`); }); } catch (error) { console.error('Failed to start server:', error); process.exit(1); } })(); এন্ট্রিপয়েন্ট ফাইল বিকাশের জন্য, আমাদের , , , , , এর জন্য সেটিংস থাকতে হবে। আমি নিম্নলিখিত নিবন্ধে বর্ণিত সেই সমস্ত ফাইলগুলি: । typscript lint jest bable prettier nodemon এক্সপ্রেস-এ পোস্টগ্রেস এবং নক্স সহ একটি Node.js সার্ভার তৈরি করা সমস্ত সেটিংস কনফিগার করার পরে এবং এন্ট্রি পয়েন্ট তৈরি করার পরে, চালানোর ফলে সার্ভার শুরু করা উচিত এবং আপনি নিম্নলিখিতগুলির মতো আউটপুট দেখতে পাবেন: npm run dev ./src/index.ts 1.7 KiB [built] [code generated] external "dotenv" 42 bytes [built] [code generated] external "process" 42 bytes [built] [code generated] external "express" 42 bytes [built] [code generated] external "body-parser" 42 bytes [built] [code generated] external "cors" 42 bytes [built] [code generated] webpack 5.90.3 compiled successfully in 751 ms [nodemon] restarting due to changes... [nodemon] starting `node dist/bundle.js` Server is running on port 9999 পরবর্তী, নেভিগেট করুন যেখানে আমরা আমাদের শেষ পয়েন্ট পরীক্ষা করার জন্য নিবেদিত একটি সংগ্রহ স্থাপন করব। নতুন সংগ্রহে, একটি নতুন অনুরোধ যোগ করুন, টিপুন (ম্যাকে, তবে কীগুলি আপনার OS এর উপর নির্ভর করে), এবং এটিকে হিসাবে নাম দিন। পোস্টম্যান GET cmd + E health URL এর জন্য এন্টার যোগ করুন: । এর জন্য, একটি নতুন ভেরিয়েবল যোগ করুন যা আপনি সংগ্রহ জুড়ে ব্যবহার করতে যাচ্ছেন: {{BASE_URI}}/health BASE_URI http://localhost:9999/api/v1 তারপরে, কেবল 'পাঠান' বোতামটি ক্লিক করুন, এবং আপনার প্রতিক্রিয়া বডিটি পর্যবেক্ষণ করা উচিত: { "message": "OK" } তথ্যশালা এগিয়ে যাওয়ার আগে, আমাদের ডাটাবেস আপ এবং চলমান থাকা অত্যন্ত গুরুত্বপূর্ণ। আমরা দিয়ে এটি চালু করে এটি সম্পন্ন করব। ডাটাবেস অ্যাক্সেস এবং পরিচালনা করতে, আপনি বিভিন্ন উন্নয়ন প্ল্যাটফর্ম ব্যবহার করতে পারেন . docker-compose পিজিএডমিন ব্যক্তিগতভাবে, আমি ব্যবহার করতে পছন্দ করি , যা দক্ষ পরিচালনার জন্য PostgreSQL ডাটাবেসে নিরবচ্ছিন্ন সংযোগ সক্ষম করে এমন একটি ড্রাইভার দিয়ে সজ্জিত। রুবিমাইন আমাদের প্রয়োজনীয় কী, পাসওয়ার্ড এবং পরীক্ষার নাম সহ ফাইল দরকার: .env PORT=9999 WEB_HOST="localhost" # DB DB_HOST="localhost" DB_PORT=5432 DB_NAME="user_flow_boilerplate" DB_USER="username_123" DB_PASSWORD="SomeParole999" # User DEFAULT_PASSWORD="SomeParole999" JWT_SECRET="6f1d7e9b9ba56476ae2f4bdebf667d88eeee6e6c98c68f392ed39f7cf6e51c5a" # Test User TEST_EMAIL="test_email@test.com" TEST_USERNAME="test_username" TEST_PASSWORD="SomeParole999" # Redis REDIS_HOST="localhost" REDIS_PORT=6379 REDIS_DB=0 REDIS_PASSWORD="SomeParole999" ডাটাবেসের সাথে সংযোগের জন্য env, রেডিস, এবং বীজের জন্য পরীক্ষার মান ভয় পাবেন না, আমি এলোমেলোভাবে তৈরি করেছি যাতে এটি আরও খাঁটি উপায়ে ব্যাখ্যা করা যায়। সুতরাং, প্রকল্পের মূলে একটি ফাইল তৈরি করা যাক: JWT_SECRET docker-compose.yml version: '3.6' volumes: data: services: database: build: context: . dockerfile: postgres.dockerfile image: postgres:latest container_name: postgres environment: TZ: Europe/Madrid POSTGRES_DB: ${DB_NAME} POSTGRES_USER: ${DB_USER} POSTGRES_PASSWORD: ${DB_PASSWORD} networks: - default volumes: - data:/var/lib/postgresql/data ports: - "5432:5432" restart: unless-stopped redis: image: redis:latest container_name: redis command: redis-server --requirepass ${REDIS_PASSWORD} networks: - default ports: - "6379:6379" restart: unless-stopped পরিষেবাগুলির সাথে ডকার-কম্পোজ ফাইল দ্রুত সংযোগের জন্য আমরা ডকারে দুটি পরিষেবা চালু করতে যাচ্ছি। ডাটাবেস বা রেডিসে দ্রুত অ্যাক্সেসের সুবিধার্থে আমি এই প্রক্রিয়াটিকে সুগম করেছি, আমাদের দক্ষতার সাথে ডেটা পুনরুদ্ধার করার অনুমতি দেয়। সুতরাং, আসুন সেই পরিষেবাগুলি চালাই , এবং আমাদের নিম্নলিখিত আউটপুটের পরে আউটপুট দেখতে সক্ষম হতে হবে: docker-compose up docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES e4bef95de1dd postgres:latest "docker-entrypoint.s…" About a minute ago Up About a minute 0.0.0.0:5432->5432/tcp postgres 365e3a68351a redis:latest "docker-entrypoint.s…" About a minute ago Up About a minute 0.0.0.0:6379->6379/tcp redis এখন, আমাদের ফাইলটি তৈরি করতে হবে যেখানে আমরা অ্যাপ্লিকেশনের জন্য আমাদের প্রকারগুলি সংরক্ষণ করি: src/@types/index.ts export enum Role { Admin = 'admin', Blogger = 'blogger', } export type UserSession = { id: number; }; export type DatabaseDate = { created_at: Date; updated_at: Date; }; export type DefaultUserData = { role: Role; }; export interface User extends DatabaseDate { id: number; email: string; username: string; password: string; role: Role; } সেবা জন্য প্রকার এই মুহুর্তে, সংযোগ, স্থানান্তর এবং বীজের জন্য আপনার প্রকল্পের রুট এবং ডাটাবেস ফোল্ডারে থাকতে হবে। knexfile.ts আমি একটি বিশদ ব্যাখ্যা রেখেছি। পোস্টগ্রেসের সাথে একটি Node.js সার্ভার তৈরি করার একটি বিশদ ব্যাখ্যা রেখেছি এবং কীভাবে ব্যবহারকারীদেরকে ডাটাবেসে স্থানান্তর করতে হবে এবং যেখানে আমরা সেই env ভেরিয়েবলগুলি ব্যবহার করছি সে সম্পর্কে এক্সপ্রেস নিবন্ধে Knex-এ আমরা একই পৃষ্ঠায় আছি তা নিশ্চিত করতে আমি বিশেষভাবে মাইগ্রেশন পরীক্ষা করতে চাই। আমরা ইতিমধ্যে আমাদের পরিষেবাগুলি চালু করেছি, এবং আমাদের ডাটাবেসের সংযোগ পরীক্ষা করতে সক্ষম হতে হবে৷ docker exec -it postgres psql -U username_123 user_flow_boilerplate সংযোগটি ভাল হলে, আপনি কনসোলে থাকবেন। ঠিক আছে, যদি সংযোগে কোন সমস্যা না থাকে, তাহলে আমাদের টেবিলগুলি সেখানে স্থানান্তর করতে সক্ষম হওয়া উচিত। । তারপর আপনার ডাটাবেসের মধ্যে আপনার টেবিলে নতুন যোগ করা কলামগুলি পর্যবেক্ষণ করা উচিত। psql knex migrate:latest users আসুন এটিকে জাল ডেটা দিয়ে করি knex seed:run সুতরাং, আমরা এখন ডাটাবেস ম্যানিপুলেট করার জন্য সজ্জিত, আমাদের প্রয়োজন অনুসারে ব্যবহারকারীদের যোগ, মুছে বা আপডেট করার অনুমতি দেয়। রাউটার অবশেষে, আমরা সেটিংস এবং প্রস্তুতি সম্পর্কে ভুলে যেতে পারি এবং বিশেষভাবে ব্যবহারকারীর প্রবাহের উপর ফোকাস করতে পারি। এর জন্য, আমাদের একটি রাউটার তৈরি করতে হবে। আমাদের সেই রাউটার দ্বারা নিম্নলিখিত ক্রিয়াকলাপগুলি পরিচালনা করতে হবে: , , , , । login logout signup delete_user update_user এর জন্য, এ, নিম্নলিখিত কোডটি যোগ করুন: src/routes/index.ts import { Router } from 'express'; import { authRouter } from 'src/routes/authRouter'; import { healthController } from 'src/controllers/healthController'; import { sessionController } from 'src/controllers/sessionController'; import { authMiddleware } from 'src/middlewares/authMiddleware'; import { userRouter } from 'src/routes/userRouter'; export const router = Router({ mergeParams: true }); router.get('/health', healthController); router.use('/auth', authRouter); router.get('/session', authMiddleware, sessionController); router.use('/user', authMiddleware, userRouter); router.use((_, res) => { return res.status(404).json({ message: 'Not Found' }); }); রুট ফাইল আপনি দেখতে পাচ্ছেন, শুরুতে, আমরা রুট যোগ করেছি যা আমরা ইতিমধ্যে পরীক্ষা করেছি। তাহলে, আসুন সেখানে সেই রুটগুলি প্রয়োগ করতে এন্ট্রি পয়েন্টটি আপডেট করি। প্রথমত, আগের মুছে ফেলুন। /health get -> REMOVE -> app.get('/api/v1/health', (req, res) => res.status(200).json({ message: 'OK' })); এবং ফাইলের শীর্ষে যোগ করুন: import { router } from 'src/routes'; // ... app.use(cors()); app.use('/api/v1', router); এবং কোড সহ পরীক্ষার জন্য প্রথম নিয়ামক তৈরি করুন: src/controllers/healthController.ts health import { Request, Response } from 'express'; export const healthController = (_: Request, res: Response) => res.status(200).send('ok'); স্বাস্থ্য নিয়ন্ত্রক এখন, রাউটারে ফিরে আসা যাক, এবং রুটগুলিতে আমাদের আরও কী যুক্ত করতে হবে তা পরীক্ষা করা যাক। আমাদের আরও দুটি ফাইল যোগ করতে হবে: এবং authRouter.ts userRouter.ts import { Router } from 'express'; import { signUpController } from 'src/controllers/auth/signUpController'; import { loginController } from 'src/controllers/auth/loginController'; export const authRouter = Router(); authRouter.post('/signup', signUpController); authRouter.post('/login', loginController); প্রমাণ রাউটার import { Router } from 'express'; import { updateUserController } from 'src/controllers/user/updateUserController'; import { deleteUserController } from 'src/controllers/user/deleteUserController'; import { logoutController } from 'src/controllers/user/logoutController'; import { updatePasswordController } from 'src/controllers/user/updatePasswordController'; export const userRouter = Router(); userRouter.patch('/', updateUserController); userRouter.delete('/', deleteUserController); userRouter.post('/logout', logoutController); userRouter.post('/update-password', updatePasswordController); ব্যবহারকারী রাউটার আমি পঠনযোগ্যতা এবং বিচ্ছিন্ন কার্যকারিতা বজায় রাখার দায়িত্বের জন্য এই যুক্তিটিকে ভাগ করেছি। সেই সমস্ত রুটের কন্ট্রোলারের প্রয়োজন যেখানে আমরা লজিক পরিচালনা করতে যাচ্ছি। প্রমাণীকরণ এবং স্বাস্থ্য রুটগুলির প্রমাণীকরণ মিডলওয়্যারের প্রয়োজন নেই, তাই সেই রুটগুলি সুরক্ষিত নয়, তবে যদি কোনও মিল না থাকে তবে আমরা একটি স্থিতি 404 পেতে যাচ্ছি। router.get('/health', healthController); router.use('/auth', authRouter); এখন, যেহেতু আমরা সমস্ত রুট সেট আপ করেছি, আমাদের ব্যবহারকারী মডেল সেট করতে হবে। ব্যবহারকারী মডেল আমি ব্যবহারকারী মডেলের জন্য একটি বেস মডেল ব্যবহার করব, যেখান থেকে আমি CRUD পদ্ধতিগুলি পুনরায় ব্যবহার করব। যদিও আমি পূর্বে অন্য একটি মডেল তৈরি কভার করেছি , আরও ভাল দৃশ্যমানতা এবং বোঝার জন্য আমি এখানে বেস মডেল অন্তর্ভুক্ত করব। এ তৈরি করুন নিবন্ধ src/models/Model.ts import { database } from 'root/database'; export abstract class Model { protected static tableName?: string; protected static get table() { if (!this.tableName) { throw new Error('The table name must be defined for the model.'); } return database(this.tableName); } public static async insert<Payload>(data: Payload): Promise<{ id: number; }> { const [result] = await this.table.insert(data).returning('id'); return result; } public static async updateOneById<Payload>( id: number, data: Payload ): Promise<{ id: number; }> { const [result] = await this.table.where({ id }).update(data).returning('id'); return result; } public static async delete(id: number): Promise<number> { return this.table.where({ id }).del(); } public static async findOneById<Result>(id: number): Promise<Result> { return this.table.where('id', id).first(); } public static async findOneBy<Payload, Result>(data: Payload): Promise<Result> { return this.table.where(data as string).first(); } } বেস মডেল বেস মডেলের সাথে, আমাদের একই ফোল্ডারে তৈরি করতে সক্ষম হতে হবে: UserModel.ts import { Model } from 'src/models/Model'; import { Role, User, DefaultUserData } from 'src/@types'; export class UserModel extends Model { static tableName = 'users'; public static async create<Payload>(data: Payload) { return super.insert<Payload & DefaultUserData>({ ...data, role: data.role || Role.Blogger, }); } public static findByEmail(email: string): Promise<User | null> { return this.findOneBy< { email: string; }, User >({ email }); } public static findByUsername(username: string): Promise<User | null> { return this.findOneBy< { username: string; }, User >({ username }); } } ব্যবহারকারী মডেল ব্যবহারকারীর মডেলে, পেলোড থেকে প্রদান না করলে আমি ডিফল্টরূপে সেট করি। এবং এখন যেহেতু আমাদের মডেলগুলি প্রস্তুত আছে, আমরা সেগুলিকে আমাদের কন্ট্রোলার এবং মিডলওয়্যারের মধ্যে ব্যবহার করতে এগিয়ে যেতে পারি। role Auth Middleware একটি Node.js অ্যাপ্লিকেশনের auth Middleware আগত অনুরোধগুলি প্রমাণীকরণের জন্য দায়ী, নিশ্চিত করে যে তারা বৈধ এবং অনুমোদিত ব্যবহারকারীদের কাছ থেকে আসছে। এটি সাধারণত আগত অনুরোধগুলিকে বাধা দেয়, প্রমাণীকরণ টোকেন বা শংসাপত্রগুলি বের করে এবং এই ক্ষেত্রে JWT (JSON ওয়েব টোকেন) এর মতো পূর্বনির্ধারিত প্রমাণীকরণ প্রক্রিয়ার বিরুদ্ধে তাদের বৈধতা যাচাই করে। যদি প্রমাণীকরণ প্রক্রিয়া সফল হয়, মিডলওয়্যার অনুরোধটিকে অনুরোধ-প্রতিক্রিয়া চক্রের পরবর্তী হ্যান্ডলারের কাছে যেতে দেয়। যাইহোক, যদি প্রমাণীকরণ ব্যর্থ হয়, এটি একটি উপযুক্ত HTTP স্ট্যাটাস কোড (যেমন, 401 অননুমোদিত) দিয়ে সাড়া দেয় এবং ঐচ্ছিকভাবে একটি ত্রুটি বার্তা প্রদান করে। ফোল্ডার তৈরি করুন এবং নিম্নলিখিত কোড সহ একটি ফাইল যোগ করুন: src/middlewares authMiddleware.ts import { jwt } from 'src/utils/jwt'; import { Redis } from 'src/redis'; import type { Request, Response, NextFunction } from 'express'; import type { UserSession } from 'src/@types'; export async function authMiddleware(req: Request, res: Response, next: NextFunction) { const authHeader = req.headers['authorization']; const token = authHeader && authHeader.split(' ')[1]; const JWT_SECRET = process.env.JWT_SECRET; if (!token) return res.sendStatus(401); if (!JWT_SECRET) { console.error('JWT_SECRET Not Found'); return res.sendStatus(500); } if (!token) return res.status(401).json({ error: 'Token not provided' }); try { const userSession = await jwt.verify<UserSession>(token); if (!userSession) { return res.sendStatus(401); } const storedToken = await Redis.getSession(userSession.id); if (!storedToken || storedToken !== token) { return res.sendStatus(401); } req.user = userSession; next(); } catch (error) { console.error('JWT_ERROR', error); return res.sendStatus(401); } } Auth মিডলওয়্যার ফাইল auth মিডলওয়্যার অনুরোধের শিরোনাম থেকে JWT টোকেন বের করে, JWT লাইব্রেরি ব্যবহার করে এর বৈধতা যাচাই করে এবং Redis-এ সংরক্ষিত টোকেনের সাথে মেলে কিনা তা পরীক্ষা করে। যদি টোকেনটি বৈধ হয় এবং সঞ্চিত টোকেনের সাথে মেলে, মিডলওয়্যার অনুরোধ বস্তু ( ) এ প্রমাণীকৃত ব্যবহারকারী সেশন সেট করে এবং পরবর্তী মিডলওয়্যার বা রুট হ্যান্ডলারের কাছে নিয়ন্ত্রণ পাস করার জন্য ফাংশনটি কল করে। অন্যথায়, এটি একটি 401 স্ট্যাটাস কোড দিয়ে সাড়া দেয় যা প্রমাণীকরণ ব্যর্থতা নির্দেশ করে। req.user next() JSON ওয়েব টোকেন আসুন jwt এর জন্য ব্যবহার পর্যালোচনা করি। নিম্নলিখিত কোড সহ ফাইল তৈরি করুন: src/utils/jwt.ts require('dotenv').config(); import jsonwebtoken from 'jsonwebtoken'; const JWT_SECRET = process.env.JWT_SECRET as string; export const jwt = { verify: <Result>(token: string): Promise<Result> => { if (!JWT_SECRET) { throw new Error('JWT_SECRET not found in environment variables!'); } return new Promise((resolve, reject) => { jsonwebtoken.verify(token, JWT_SECRET, (error, decoded) => { if (error) { reject(error); } else { resolve(decoded as Result); } }); }); }, sign: (payload: string | object | Buffer): Promise<string> => { if (!JWT_SECRET) { throw new Error('JWT_SECRET not found in environment variables!'); } return new Promise((resolve, reject) => { try { resolve(jsonwebtoken.sign(payload, JWT_SECRET)); } catch (error) { reject(error); } }); }, }; JWT ইউটিলিটি ফাইল এই ইউটিলিটি Node.js অ্যাপ্লিকেশনের মধ্যে JSON ওয়েব টোকেন পরিচালনার ক্ষেত্রে একটি গুরুত্বপূর্ণ ভূমিকা পালন করে। অবজেক্ট লাইব্রেরি ব্যবহার করে, JWTs স্বাক্ষর এবং যাচাইকরণ উভয়ের জন্য ফাংশন রপ্তানি করে। এই ফাংশনগুলি জেডব্লিউটি তৈরি এবং যাচাইকরণের সুবিধা দেয়, যা অ্যাপ্লিকেশনে প্রমাণীকরণ প্রক্রিয়া বাস্তবায়নের জন্য অপরিহার্য। jwt jsonwebtoken পরিবেশ পরিবর্তনশীল ব্যবস্থাপনার জন্য সর্বোত্তম অনুশীলনগুলি মেনে চলার সময় ইউটিলিটি, Node.js অ্যাপ্লিকেশনের মধ্যে নিরাপদ প্রমাণীকরণ প্রক্রিয়া নিশ্চিত করে JWTs পরিচালনার কার্যকারিতাকে অন্তর্ভুক্ত করে। রেডিস ডাটাবেস, ক্যাশে এবং বার্তা ব্রোকার হিসাবে ব্যবহৃত হয়। ক্যাশিং, সেশন ম্যানেজমেন্ট, রিয়েল-টাইম অ্যানালিটিক্স, মেসেজিং সারি, লিডারবোর্ড এবং আরও অনেক কিছু সহ বিভিন্ন ব্যবহারের ক্ষেত্রে সাধারণত ব্যবহৃত হয়। Redis থেকে টোকেন চেক করা JWT টোকেনের জন্য নিরাপত্তা এবং বৈধতার একটি অতিরিক্ত স্তর হিসাবে কাজ করে। এর সেটিংসে ডুব দেওয়া যাক। এর জন্য, নিম্নলিখিত কোড সহ ফাইল তৈরি করুন: src/redis/index.ts require('dotenv').config({ path: '../../.env', }); import process from 'process'; import * as redis from 'redis'; const client = redis.createClient({ url: `redis://:${process.env.REDIS_PASSWORD}@${process.env.REDIS_HOST}:${process.env.REDIS_PORT}`, }); client.on('error', error => console.error('Redis Client Error', error)); const connect = async () => { try { await client.connect(); console.log('Connected to Redis'); } catch (err) { console.error(`Could not connect to Redis: ${err}`); process.exit(1); } }; class Redis { public static setSession(userId: number, token: string) { if (!userId) throw new Error('userId is required'); if (!token) throw new Error('token is required'); try { return client.set(`session:${userId}`, token); } catch (error) { console.error(error); } } public static getSession(userId: number) { if (!userId) throw new Error('userId is required'); return client.get(`session:${userId}`); } public static deleteSession(userId: string) { if (!userId) throw new Error('userId is required'); try { return client.del(`session:${userId}`); } catch (error) { console.error(error); } } } export { client, connect, Redis }; রিডিস সেশন স্টোর Redis দ্বারা, আমরা ব্যবহারকারীর সেশন টোকেন সংরক্ষণ এবং পরিচালনা করতে যাচ্ছি। অথ মিডলওয়্যারে, JWT টোকেনের সত্যতা যাচাই করার পরে, মিডলওয়্যার টোকেনটি বিদ্যমান কিনা এবং সংশ্লিষ্ট ব্যবহারকারীর সেশনের জন্য Redis-এ সংরক্ষিত একটির সাথে মেলে কিনা তা পরীক্ষা করে। এটি নিশ্চিত করতে সাহায্য করে যে শুধুমাত্র বৈধ এবং অনুমোদিত ব্যবহারকারীরা সুরক্ষিত রুটগুলি অ্যাক্সেস করতে পারে৷ রেডিস ব্যবহারকারীর সেশন টোকেন বজায় রাখার জন্য একটি মূল-মূল্যের দোকান হিসাবে ব্যবহৃত হয়। যখন একজন ব্যবহারকারী লগ ইন করেন বা প্রমাণীকরণ করেন, তখন তাদের সেশন টোকেন রেডিসে সংরক্ষণ করা হয়। এটি পরবর্তী প্রমাণীকরণ চেকের সময় সেশন টোকেনগুলির দক্ষ এবং দ্রুত পুনরুদ্ধারের অনুমতি দেয়। Redis দক্ষ সেশন পরিচালনার জন্য অথ মিডলওয়্যারে ব্যবহার করা হয়, যখন Redis-সম্পর্কিত ফাইলটি Redis সার্ভারের সাথে কনফিগারেশন এবং সংযোগ পরিচালনা করে এবং অ্যাপ্লিকেশনের অন্যান্য অংশে Redis-এর সাথে ইন্টারঅ্যাক্ট করার জন্য ফাংশন প্রদান করে। এই সেটআপটি নিরাপদ এবং নির্ভরযোগ্য প্রমাণীকরণ প্রক্রিয়া নিশ্চিত করে, ব্যবহারকারী সেশন টোকেনগুলি Redis-এ সংরক্ষিত এবং পরিচালিত হয়। শেষ অংশটি হল আমাদের এন্ট্রি পয়েন্টে রেডিসের সাথে সংযোগ করতে হবে: // all imports import * as Redis from 'src/redis'; const app = express(); const PORT = process.env.PORT || 9999; // middlewares (async () => { try { await Redis.connect(); app.listen(PORT, async () => { console.log(`Server is running on port ${PORT}`); }); } catch (error) { console.error('Failed to start server:', error); process.exit(1); } })(); Redis এর সাথে সংযোগ করুন প্রমাণীকরণ প্রস্তুতি সম্পন্ন করার পর, আমরা এখন আমাদের ফোকাস কন্ট্রোলারের দিকে সরাতে পারি। কন্ট্রোলার রুটের কন্ট্রোলাররা উদ্বেগকে আলাদা করে এবং কোড রক্ষণাবেক্ষণের প্রচার করে অ্যাপ্লিকেশনের যুক্তি সংগঠিত করতে সাহায্য করে। আমরা ইতিমধ্যে স্বাস্থ্য পরীক্ষার জন্য নিয়ামক তৈরি করেছি। পরবর্তী, আমরা ব্যবহারকারীর সাথে ক্রিয়াকলাপ পরিচালনা করার জন্য কন্ট্রোলার তৈরি করতে এগিয়ে যাব। আমরা যে প্রথম নিয়ামকটি নিতে যাচ্ছি তা হল যা নিম্নলিখিত কোড সহ এ থাকতে হবে: sessionController.ts src/controllers import { Request, Response } from 'express'; import { UserModel } from 'src/models/UserModel'; import type { User } from 'src/@types'; export const sessionController = async (req: Request, res: Response) => { if (!req.user) return res.sendStatus(401); try { const user = await UserModel.findOneById<User>(req.user.id); if (user) { return res.status(200).json(user); } else { return res.sendStatus(401); } } catch (error) { return res.sendStatus(500); } }; সেশন কন্ট্রোলার এই কন্ট্রোলারটি একটি সেশন-সম্পর্কিত এন্ডপয়েন্ট পরিচালনা করার উদ্দেশ্যে কাজ করে, সম্ভবত বর্তমানে প্রমাণীকৃত ব্যবহারকারী সম্পর্কে তথ্য পুনরুদ্ধারের জন্য দায়ী। নিম্নলিখিত কারণে আমাদের এই নিয়ামক প্রয়োজন: এই নিয়ামকটি অ্যাপ্লিকেশনটিকে ব্যবহারকারীর সেশন সম্পর্কে তথ্য পুনরুদ্ধার করার অনুমতি দেয়, যেমন তাদের ব্যবহারকারীর প্রোফাইল বা অন্যান্য প্রাসঙ্গিক ডেটা। এই তথ্য ব্যবহারকারীর অভিজ্ঞতা কাস্টমাইজ করতে বা ব্যবহারকারীর প্রোফাইলের উপর ভিত্তি করে ব্যক্তিগতকৃত সামগ্রী প্রদানের জন্য উপযোগী হতে পারে। ব্যবহারকারীর সেশনের তথ্য: বিদ্যমান কিনা তা পরীক্ষা করে, নিয়ন্ত্রক নিশ্চিত করে যে শুধুমাত্র প্রমাণীকৃত ব্যবহারকারীরা এন্ডপয়েন্ট অ্যাক্সেস করতে পারে। এটি প্রমাণীকরণ এবং অনুমোদনের নিয়মগুলি প্রয়োগ করতে সাহায্য করে, এটি নিশ্চিত করে যে সংবেদনশীল ব্যবহারকারীর ডেটা শুধুমাত্র অনুমোদিত ব্যবহারকারীদের কাছে অ্যাক্সেসযোগ্য। প্রমাণীকরণ এবং অনুমোদন: req.user নিয়ামক তাদের সেশন আইডির উপর ভিত্তি করে ব্যবহারকারীর তথ্য পুনরুদ্ধার করতে ডাটাবেস ( ব্যবহার করে) জিজ্ঞাসা করে। এটি অ্যাপ্লিকেশনটিকে গতিশীলভাবে ব্যবহারকারী-নির্দিষ্ট ডেটা আনার অনুমতি দেয়, প্রতিটি ব্যবহারকারীর জন্য একটি উপযোগী অভিজ্ঞতা প্রদান করে। এই অংশটি অবশ্যই Redis ক্যাশে দ্বারা উন্নত করা যেতে পারে: ব্যবহারকারীর প্রোফাইল পুনরুদ্ধার: UserModel import { Request, Response } from 'express'; import { UserModel } from 'src/models/UserModel'; import { Redis } from 'src/redis'; import type { User } from 'src/@types'; export const sessionController = async (req: Request, res: Response) => { if (!req.user) return res.sendStatus(401); try { const cachedProfile = await Redis.getSession(req.user.id); if (cachedProfile) { return res.status(200).json(JSON.parse(cachedProfile)); } else { const user = await UserModel.findOneById<User>(req.user.id); if (user) { await Redis.setSession(req.user.id, JSON.stringify(user), CACHE_EXPIRATION); return res.status(200).json(user); } else { return res.sendStatus(401); } } } catch (error) { console.error('Error retrieving user profile:', error); return res.sendStatus(500); } }; Redis সেট সেশন সহ সেশন কন্ট্রোলার ফাইল সেকেন্ডের মধ্যে ক্যাশের মেয়াদ শেষ হওয়ার সময় নির্দিষ্ট করতে আমরা একটি ধ্রুবক সংজ্ঞায়িত করি। এই উদাহরণে, এটি 3600 সেকেন্ড (1 ঘন্টা) সেট করা হয়েছে। ক্যাশে করা ডেটা পর্যায়ক্রমে রিফ্রেশ করা হয়, ব্যবহারকারীদের কাছে পুরানো ডেটা সরবরাহ করা থেকে বাধা দেয় এবং ক্যাশে ডেটার অখণ্ডতা বজায় রাখে। CACHE_EXPIRATION তৈরি করতে এগিয়ে যাওয়ার আগে, যা আমাদের অ্যাপ্লিকেশনে নতুন ব্যবহারকারীদের জন্য সাইন-আপ প্রক্রিয়া পরিচালনা করে, আসুন স্কিমাটি পর্যালোচনা করি: signUpController আমাদের ক্ষেত্রে, ডাটাবেস ইমেলে বিদ্যমান একটি দিয়ে সাইন আপ করার চেষ্টা করার সময়, আমরা ব্যবহারকারীর অস্তিত্ব আছে কিনা তা স্পষ্টভাবে প্রকাশ না করে ব্যবহারকারীর গোপনীয়তাকে অগ্রাধিকার দিই। পরিবর্তে, আমরা উল্লেখ করে একটি জেনেরিক বার্তা দিয়ে ক্লায়েন্টকে অবহিত করি। Invalid email or password এই পদ্ধতিটি ক্লায়েন্টকে বিদ্যমান ব্যবহারকারীদের সম্পর্কে অপ্রয়োজনীয় তথ্য প্রকাশ না করে বৈধ শংসাপত্র জমা দিতে উত্সাহিত করে। এখন আসুন তৈরি করি এবং নিম্নলিখিত কোডটি যোগ করি: src/controllers/auth/signUpController.ts import bcrypt from 'bcrypt'; import { jwt } from 'src/utils/jwt'; import { Request, Response } from 'express'; import { validate } from 'src/helpers/validation/validate'; import { userSchema } from 'src/helpers/validation/schemas/userSchema'; import { UserModel } from 'src/models/UserModel'; import { Redis } from 'src/redis'; import type { User } from 'src/@types'; import { getRandomString } from 'src/utils/getRandomString'; type Payload = Omit<User, 'id' | 'created_at' | 'updated_at' | 'role'>; export async function signUpController(req: Request, res: Response) { const { email, password }: Payload = req.body; const validation = validate<Payload>(req.body, userSchema); if (!validation.isValid) { return res.status(400).send(`Invalid ${validation.invalidKey}`); } try { const user = await UserModel.findOneBy({ email }); if (user) { return res.status(400).json({ message: 'Invalid email or password' }); } const hashedPassword = (await bcrypt.hash(password, 10)) as string; const username = `${email.split('@')[0]}${getRandomString(5)}`; const createdUser = await UserModel.create<Payload>({ email, password: hashedPassword, username, }); const token = await jwt.sign({ id: createdUser.id, }); await Redis.setSession(createdUser.id, token); res.status(200).json({ token, }); } catch (error) { return res.sendStatus(500); } } সাইন আপ কন্ট্রোলার নিয়ামক ব্যবহারকারীর ইমেল এবং পাসওয়ার্ড সম্বলিত একটি অনুরোধ গ্রহণ করে, সাধারণত একটি সাইন-আপ ফর্ম থেকে৷ এটি প্রয়োজনীয় বিন্যাস পূরণ করে তা নিশ্চিত করতে পূর্বনির্ধারিত বিরুদ্ধে আগত ডেটা যাচাই করে। userSchema যদি বৈধতা সফলভাবে পাস হয়, কোন বিদ্যমান ব্যবহারকারী এবং বৈধ ক্ষেত্র নির্দেশ করে, নিয়ামক ব্যবহার করে পাসওয়ার্ড হ্যাশ করতে এগিয়ে যায়, একটি তৈরি করে, এবং ব্যবহার করে ব্যবহারকারী তৈরি করে। bcrypt.hash username UserModel.create অবশেষে, এটি ব্যবহার করে একটি তৈরি করে, এ ডেটা সেট করে এবং ব্যবহারকারীকে ফেরত পাঠায়। jwt token Redis session token এখন, একটি লগইন কন্ট্রোলার তৈরিতে ফোকাস করা যাক। ফাইল তৈরি করুন : src/controllers/auth/loginController.ts require('dotenv').config({ path: '../../.env', }); import bcrypt from 'bcrypt'; import { Request, Response } from 'express'; import { jwt } from 'src/utils/jwt'; import { UserModel } from 'src/models/UserModel'; import { Redis } from 'src/redis'; export async function loginController(req: Request, res: Response) { const { email, password } = req.body; if (!email || !password) { return res.status(400).json({ message: 'Invalid email or password' }); } try { const user = await UserModel.findByEmail(email); if (user) { const isValidPassword = await bcrypt.compare(password, user.password); if (!isValidPassword) { return res.status(400).json({ message: 'Invalid email or password' }); } const token: string = await jwt.sign({ id: user.id, }); await Redis.setSession(user.id, token); res.status(200).json({ token }); } else { return res.status(400).json({ message: 'Invalid email or password' }); } } catch (error) { console.error(error); return res.sendStatus(500); } } লগইন কন্ট্রোলার মূলত, আমরা প্রদত্ত ক্ষেত্রগুলিকে যাচাই করে এবং তারপর ব্যবহারকারীর অস্তিত্ব পরীক্ষা করে শুরু করি। যদি কোনো ব্যবহারকারী খুঁজে না পাওয়া যায়, আমরা আচরণের মতো বার্তা সহ একটি 400 স্ট্যাটাস কোড দিয়ে প্রতিক্রিয়া জানাই। signupController Invalid email or password যদি কোনো ব্যবহারকারী থাকে, আমরা ব্যবহার করে ডাটাবেসে সংরক্ষিত হ্যাশ করা পাসওয়ার্ডের সাথে প্রদত্ত পাসওয়ার্ডের তুলনা করতে এগিয়ে যাই। bcrypt.compare যদি পাসওয়ার্ড মেলে না, আমরা পরিচিত বার্তা 'অবৈধ ইমেল বা পাসওয়ার্ড' দিয়ে প্রতিক্রিয়া জানাই। অবশেষে, সফল প্রমাণীকরণের পরে, আমরা একটি টোকেন তৈরি করি, সেশনটি Redis-এ সেট করি এবং টোকেনটি ক্লায়েন্টের কাছে ফেরত পাঠাই। আসুন আমাদের সুরক্ষিত কন্ট্রোলারগুলি পর্যালোচনা করি, যা মিডলওয়্যার থেকে প্রাপ্ত একটি user_id উপস্থিতির উপর নির্ভর করে। এই কন্ট্রোলারগুলির মধ্যে কাজ করার জন্য আমরা ধারাবাহিকভাবে এই user_id-এর উপর নির্ভর করি। যে ক্ষেত্রে অনুরোধে শিরোনাম নেই, আমাদের অবশ্যই একটি স্ট্যাটাস কোড দিয়ে প্রতিক্রিয়া জানাতে হবে। authorization 401 const authHeader = req.headers['authorization']; নিম্নলিখিত কোড দিয়ে ফাইল তৈরি করুন: src/controllers/user/logoutController.ts import type { Request, Response } from 'express'; import { Redis } from 'src/redis'; export async function logoutController(req: Request, res: Response) { try { await Redis.deleteSession(req.user.id); return res.sendStatus(200); } catch (error) { return res.sendStatus(500); } } লগআউট কন্ট্রোলার এই , সিস্টেম থেকে একজন ব্যবহারকারীকে লগ আউট করার জন্য দায়ী। একটি অনুরোধ পাওয়ার পরে, এটি এর সাথে যুক্ত সেশনটি মুছে ফেলার জন্য Redis ক্লায়েন্টের সাথে যোগাযোগ করে। অপারেশন সফল হলে, এটি সফল লগআউট নির্দেশ করার জন্য একটি স্ট্যাটাস কোড দিয়ে সাড়া দেয়। logoutController user.id 200 যাইহোক, প্রক্রিয়া চলাকালীন একটি ত্রুটি দেখা দিলে, এটি একটি অভ্যন্তরীণ সার্ভার ত্রুটি সংকেত দিতে স্ট্যাটাস কোড দিয়ে প্রতিক্রিয়া জানায়। 500 এর পরে, আসুন ব্যবহারকারীর ডেটা মুছে ফেলার বিষয়ে আলোচনা করা যাক। তৈরি করুন এবং এই কোড যোগ করুন: src/controllers/user/deleteUserController.ts import { Request, Response } from 'express'; import { UserModel } from 'src/models/UserModel'; import { Redis } from 'src/redis'; export const deleteUserController = async (req: Request, res: Response) => { const user_id = req.user.id; try { await Redis.deleteSession(user_id); await UserModel.delete(user_id); return res.sendStatus(200); } catch (error) { return res.sendStatus(500); } }; ব্যবহারকারী নিয়ামক মুছুন যখন একটি অনুরোধ গৃহীত হয়, এটি অনুরোধ বস্তু থেকে ব্যবহারকারী আইডি বের করে, সাধারণত প্রমাণীকরণ মিডলওয়্যার থেকে প্রাপ্ত হয়। পরবর্তীকালে, এটি Redis ক্লায়েন্ট ব্যবহার করে Redis থেকে এই সাথে যুক্ত সেশন মুছে ফেলার জন্য এগিয়ে যায়। পরবর্তীতে, এটি ডাটাবেস থেকে ব্যবহারকারীর ডেটা মুছে ফেলার জন্য এর পদ্ধতি চালু করে। user_id UserModel delete সেশন এবং ব্যবহারকারীর ডেটা উভয়ই সফলভাবে মুছে ফেলার পরে, এটি সফল মোছা নির্দেশ করার জন্য স্ট্যাটাস কোডের সাথে প্রতিক্রিয়া জানায়। মুছে ফেলার প্রক্রিয়া চলাকালীন একটি ত্রুটি ঘটলে, এটি একটি অভ্যন্তরীণ সার্ভার ত্রুটি বোঝাতে স্ট্যাটাস কোড দিয়ে প্রতিক্রিয়া জানায়। 200 500 সিস্টেমে ব্যবহারকারীর ডেটা আপডেট করতে তৈরি করুন এবং ফাইলটিতে নিম্নলিখিত কোড যোগ করুন: src/controllers/user/updateUserController.ts import { Request, Response } from 'express'; import { UserModel } from 'src/models/UserModel'; import { filterObject } from 'src/utils/filterObject'; type Payload = { first_name?: string; last_name?: string; username?: string; }; export const updateUserController = async (req: Request, res: Response) => { const { first_name, last_name, username } = req.body; const payload: Payload = filterObject({ first_name, last_name, username, }); try { const existingUserName = await UserModel.findByUsername(username); if (existingUserName) { return res.status(400).json({ error: 'Invalid username', }); } const updatedUser = await UserModel.updateOneById<typeof payload>(req.user.id, payload); res.status(200).json(updatedUser); } catch (error) { res.sendStatus(500); } }; ব্যবহারকারী কন্ট্রোলার আপডেট করুন একটি অনুরোধ পাওয়ার পরে, এটি অনুরোধের বডি থেকে , , এবং ক্ষেত্রগুলি বের করে। এর পরে, এটি ইউটিলিটি ফাংশন ব্যবহার করে এই ক্ষেত্রগুলিকে ফিল্টার করে তা নিশ্চিত করতে যে শুধুমাত্র বৈধ ক্ষেত্রগুলি পেলোডে অন্তর্ভুক্ত করা হয়েছে। first_name last_name username filterObject পরবর্তীকালে, এটি পরীক্ষা করে যে প্রদত্ত ডাটাবেসে ইতিমধ্যেই বিদ্যমান আছে কিনা। যদি এটি হয়, নিয়ামক একটি স্ট্যাটাস কোড এবং একটি ভুল নির্দেশ করে একটি ত্রুটি বার্তা দিয়ে প্রতিক্রিয়া জানায়৷ অনন্য হলে, নিয়ামক এর পদ্ধতি ব্যবহার করে ডাটাবেসে ব্যবহারকারীর ডেটা আপডেট করতে এগিয়ে যায়। username 400 username username UserModel updateOneById সফল আপডেটের পরে, এটি একটি স্ট্যাটাস কোড এবং আপডেট হওয়া ব্যবহারকারীর ডেটা সহ প্রতিক্রিয়া জানায়। আপডেট প্রক্রিয়া চলাকালীন কোনো ত্রুটির ক্ষেত্রে, নিয়ামক একটি অভ্যন্তরীণ সার্ভার ত্রুটি নির্দেশ করার জন্য একটি স্ট্যাটাস কোড দিয়ে প্রতিক্রিয়া জানায়। 200 500 শেষটি হবে পাসওয়ার্ড আপডেট করা, ব্যবহারকারীর ডেটা আপডেট করার মতই ধারণা, কিন্তু নতুন পাসওয়ার্ড হ্যাশ করার সাথে। আমাদের তালিকা থেকে শেষ নিয়ামকটি তৈরি করুন এবং কোডটি যোগ করুন: src/controllers/user/updatePasswordController.ts import { Request, Response } from 'express'; import { UserModel } from 'src/models/UserModel'; import bcrypt from 'bcrypt'; export const updatePasswordController = async (req: Request, res: Response) => { try { const { password } = req.body; if (!password) return res.sendStatus(400); const hashedPassword = (await bcrypt.hash(password, 10)) as string; const user = await UserModel.updateOneById(req.user.id, { password: hashedPassword }); return res.status(200).json({ id: user.id }); } catch (error) { return res.sendStatus(500); } }; পাসওয়ার্ড কন্ট্রোলার আপডেট করুন একটি অনুরোধ পাওয়ার পরে, এটি অনুরোধের বডি থেকে নতুন পাসওয়ার্ড বের করে। তারপরে অনুরোধের অংশে একটি পাসওয়ার্ড দেওয়া হয়েছে কিনা তা পরীক্ষা করে। যদি না হয়, এটি একটি স্ট্যাটাস কোডের সাথে প্রতিক্রিয়া জানায়, এটি একটি খারাপ অনুরোধ নির্দেশ করে। এর পরে, এটি 10 এর সল্ট ফ্যাক্টর সহ লাইব্রেরি ব্যবহার করে নতুন পাসওয়ার্ড হ্যাশ করে। 400 bcrypt তারপরে হ্যাশ করা পাসওয়ার্ডটি এর পদ্ধতি ব্যবহার করে ডাটাবেসে নিরাপদে সংরক্ষণ করা হয়, এটি এর সাথে সংযুক্ত করে। সফল পাসওয়ার্ড আপডেটের পরে, নিয়ামক একটি স্ট্যাটাস কোড এবং ব্যবহারকারীর আইডি ধারণকারী একটি JSON অবজেক্টের সাথে প্রতিক্রিয়া জানায়। UserModel updateOneById user.id 200 পাসওয়ার্ড আপডেট প্রক্রিয়া চলাকালীন কোনো ত্রুটির ক্ষেত্রে, নিয়ামক অন্যান্য কন্ট্রোলারের মতো একটি অভ্যন্তরীণ সার্ভার ত্রুটি নির্দেশ করতে স্ট্যাটাস কোড দিয়ে প্রতিক্রিয়া জানায়। 500 থেকে যাচাইকরণ সহায়ক এবং ইউটিলিটিগুলি পর্যালোচনা এবং সেট আপ করা নিশ্চিত করুন৷ . একবার কনফিগার করা হলে, আপনার শেষ পয়েন্টগুলি পরীক্ষা করার জন্য প্রস্তুত হওয়া উচিত। GitHub সংগ্রহস্থল আসুন সাইনআপ শেষ পয়েন্ট পরীক্ষা করা যাক: স্পষ্ট হিসাবে, আমরা একটি টোকেন পেয়েছি, যা সেশনটি পুনরুদ্ধার করতে হেডারে ব্যবহার করা হবে। আমরা সার্ভারে হেডারে অনুমোদনের টোকেন পাঠিয়েছি, এবং প্রতিক্রিয়া হিসাবে, সার্ভার আমাদের ডেটাবেস থেকে পুনরুদ্ধার করা ব্যবহারকারীর ডেটা সরবরাহ করেছে। অন্বেষণ এবং নিরাপত্তা বৈশিষ্ট্য এবং Redis ক্যাশিং সঙ্গে পরীক্ষা নির্দ্বিধায়. ফাউন্ডেশনাল মডেলের জায়গায়, আপনি অতিরিক্ত কার্যকারিতা, যেমন ব্যবহারকারীদের জন্য অ্যাকাউন্ট পুনরুদ্ধার করতে পারেন যারা তাদের পাসওয়ার্ড ভুলে গেছেন। যাইহোক, এই বিষয়টি ভবিষ্যতের নিবন্ধের জন্য সংরক্ষিত থাকবে। উপসংহার স্কেলযোগ্য পদ্ধতিতে রাউটিং এবং ব্যবহারকারীর প্রমাণীকরণ প্রবাহ পরিচালনা করা চ্যালেঞ্জিং হতে পারে। যদিও আমরা রুটগুলি সুরক্ষিত করার জন্য মিডলওয়্যার প্রয়োগ করেছি, পরিষেবাটির কার্যকারিতা এবং নির্ভরযোগ্যতা বাড়ানোর জন্য অতিরিক্ত কৌশলগুলি উপলব্ধ রয়েছে৷ আরও বর্ধিত ব্যবহারকারীর অভিজ্ঞতা পরিষ্কার ত্রুটি বার্তা প্রদান করে, কারণ ত্রুটি হ্যান্ডলিং একটি উল্লেখযোগ্য দিক থেকে যায় যার জন্য আরও ব্যাপক কভারেজ প্রয়োজন। যাইহোক, আমরা সফলভাবে প্রাথমিক প্রমাণীকরণ প্রবাহ বাস্তবায়ন করেছি, ব্যবহারকারীদের সাইন আপ করতে, তাদের অ্যাকাউন্টগুলি অ্যাক্সেস করতে, সেশন ডেটা পুনরুদ্ধার করতে, ব্যবহারকারীর তথ্য আপডেট করতে এবং অ্যাকাউন্টগুলি মুছতে সক্ষম করেছিলাম৷ আমি আশা করি আপনি এই যাত্রাটি অন্তর্দৃষ্টিপূর্ণ খুঁজে পেয়েছেন এবং ব্যবহারকারীর প্রমাণীকরণে মূল্যবান জ্ঞান অর্জন করেছেন। সম্পদ গিটহাব রেপো Knex.js প্রকাশ করা নোড অ্যাপ্লিকেশন তৈরি করুন পোস্টম্যান এছাড়াও প্রকাশিত এখানে