سلام بعد از سه سال دوباره با یه پست شاید مفید اومدم خدمتتون. فقط دوس دارم یاد گرفته هامو اشتراک بذارم تا خودمم یه محکی زده باشم.حرف بسه بریم سراغ کار.
خب اول همه توضیح بدیم که چه کاری قراره انجام بدیم.قراره که روند ثبت نام و ورود کاربر رو کار کنیم با نود جی اس، اکسپرس صد البته Mongoose .

چیا کلا قراره پیاده سازی بشه ثبت نام کاربر و لاگین کاربر، ریست کردن پسورد، ریست کردن توکن، ایمیل کردن ریست پسورد، محافظت از مسیرهای یوزر، نقش کاربر ادمین یا محدود کردن ها و کار با توکن و کوکی و ذخیره سازی کلی چیز. میز.البته فک نکنم همش توی یه مقاله حوصله سر بر نشه و تقسیمش کنم به سلسله ای از مقالات.:))

هشدار که شاید کامنت گذاری ها توی متن و اسم گذاری ها باب میل سنیور ها نباشه.و اینکه ارور هندلینگم خودتون هندل کنید دیگه .:))

چیزایی که فعلا نیاز داریم ایناس که با npm نصب شن :

  • ,bcryptjs,express,jsonwebtoken,mongoose,validator, nodemailer

یه سری فایل هم باید ساخته بشه که بخش باهاش ​​میریم جلو :

فایل اول فایل userModel.js که قرار است مدل اسکیمای یوزر رو توش بسازیم: به این شکل با کد زیر:

const mongoose = require(&quotmongoose&quot);
const validator = require(&quotvalidator&quot);
const bcrypt = require(&quotbcryptjs&quot);
const userSchema = new mongoose.Schema({
  name: {
    type: String,
    required: [true, &quotPlease tell us your name!&quot],  },
  email: {
    type: String,
    required: [true, &quotPlease provide your email&quot],
    unique: true,
    lowercase: true,
    validate: [validator.isEmail, &quotPlease provide a valid email&quot],
  },
  photo: String,
  role: {
    type: String,
    enum: [&quotadmin&quot, &quotuser&quot, &quottour-lead&quot, &quottour-guied&quot],
    default: &quotuser&quot,
  },
  password: {
    type: String,
    required: [true, &quotPlease provide a password&quot],
    minlength: 8,
    select: false,
  },
  passwordConfirm: {
    type: String,
    required: [true, &quotPlease confirm your password&quot],
    validate: {
      validator: function (el) {
        return el === this.password;
      },
      message: &quotconfirm password is incorrect&quot,
    },
  },
  passwordChangeAt: Date,
});

خب به مدل بگم که 7 فیلده : نام،ایمیل، پسورد، تایید پسورد،نقش کاربر، عکس پروفایل و تاریخ تغییر پسورد فعلا بعدا باز هم اضافه می شود. و توی ایمیل هم یه فنکشنی برای ولیدیت نوشتیم.
خب حالا که مدل رو ساختیم میریم سراغ فایل server.js شروع برنامه .چیز خاص توش نیست که بخوام کدش رو بذارم فقط کانفیگ سرور و منگو دی بی و پورت و اینا همین.

توی فایل app.js همون چیزایی که برای شروع فقط روت یوزر رو ست میکنیم:

app.use(&quot/api/v1/users&quot, userRouter);

خب حالا باید دوتا فایل بسازیم اولی برای احراز یوزر کنترلر authController و دومی برای یوزر روترuserRouter.

توی فایل اول یعنی authController دوتا میدلور داریم. یکی برای ثبت نام به اسم signUp و دیگری برای ورود کاربر.فعلا خالی خالی بسازیم و اکسپورت کنیم چون توی یوزر روتر کار داریم .بعد تک تک هرکودوم رو میریم جلو.

میدلور هارو که کنترلر ساختیم توی فایل یوزر روتر ست میکنیم.یوزر روتر:::

const express = require(&quotexpress&quot);
const authController = require(&quot../controllers/authController&quot);
const router = express.Router();
router.post(&quot/signup&quot, authController.signUp);            ایناهاش
router.post(&quot/login&quot, authController.logIn);                    ایناهاش 
module.exports = router;

خب حالا همه چی آمادس بریم سر وقت فایل کنترلر مون:

مدل و jwt رو ایمپورت میکنیم تا ازش استفاده کنیم اسمه مدلمون هم کاربر هست.

onst User = require(&quot../model/userModel&quot);
const jwt = require(&quotjsonwebtoken&quot);

یه فانکشنی مینویسیم برای ایجاد توکن نا برامون توکن تولید کنه آیدی کاربر رو به عنوان ورودی میگیره.

const signToken = (id) => {
return jwt.sign({ id }, &quotnew_secret_key_foobar&quot, {
expiresIn: &quot30d&quot,                                  
});
};

سه تا مقدار میتونیم به این متد علامت بدیم . یکیش آی دی که از اولمون گرفتیم دومی کلید سکرت که من اینجا اینو گذاشتم ولی شما اینو نذارید :)) سومی هم مدت زمان ماندگاری توکنه .که به روز و دقیقه وساعت اینا میتونید وارد کنید که من اینجا دادم 30 روز.

خیلی بهتره که کلید اسکرت و اینجور موارد رو توی فایل config.env وارد کنید و بعد از آن استفاده کنید.

مرحله بعدی ساخت فانکشن ثبت نام هست : کدو ببین و بعد توضیحات رو ببین :

exports.signUp = async (req, res) => {
const newUser = await User.create({
   name: req.body.name,
   email: req.body.email,
   password: req.body.password,
   passwordConfirm: req.body.passwordConfirm,
   passwordChangeAt: req.body.passwordChangeAt,
   role: req.body.role,
});
const token = signToken(newUser._id);
res.status(201).json({
status: &quotok&quot,
token,
data: {
newUser,
},});};

از مدل User و متد create استفاده میکنیم و با استفاده از req.body یه کاربر جدید میسازیم. بعد یه ثابت میسازیم به اسم توکن و فانکشن علامت ور صدا میزنیم و حالا که آی دی کاربر رو داریم آی دی رو بهش میدیم.

بعد هم یوزر جدید و توکن رو به آبجکت جیسون میدیم.

توجه کنید که ارور هندلینگ رو پیاده سازی کنید حتما.

خب حالا مرحله بعدی که داریم قبل از ذخیره پسورد توی دیتابیس بشه اونو رمزنگاری کنیم.چطوری اینکارو بکنیم؟ می توانید از متد توی فایل مدل یوزر استفاده کنیم. و از قلاب .pre

توی فایل مدل یوزرمون که اول همین مقاله هست این کد رو اضافه میکنیم :

//encrypt password with bcrypt hash
userSchema.pre(&quotsave&quot, async function (next) {
if (!this.isModified(&quotpassword&quot)) return next();
this.password = await bcrypt.hash(this.password, 12);
this.passwordConfirm = undefined;
next();
});

بی کریپت جی اس bcryptjs رو قبل نصب کردیم از هوک

بعد از پسوردم رو مقدار زیادی میدم که مقدار جدیدش همون پسورده که با بی کریپت هش کردیم.

در آخر هم نمی خواهم تایید کنم که پسوردم توییتبیس شود من فقط برای ولیدیت ذخیره کردن نیازش دارم برای همین مقدارش رو آندیفاین میذارم.قبلا توی خود مدل من با یه فانکشن ولیدتش کردم.

خب حالا اگر کد رو سیو کنیم میبینیم که به راحتی میره توی دیتابیس ذخیره میشه.


نکته دیگه که فعلا به role یوزر کاری نداریم بعدا برای محدودیت ایجاد کردن ازش استفاده میکنیم.البته فعلا به صورت دیفالت نقش رو user تعیین میکنه.بعدا با ادمین کار میکنیم.

به نظرم برای این قسمت کافیه.توی قسمت بعد لاگین یا ورود رو پیاده سازی کنیم.با توکن بیشتر کار کنیم و ببینیم داستان توکن و پسورد و لاگین چطوریه.

باز نکته اگر اشتباهات املایی داشتم یا جایی از ه کسره استفاده کردم یا فانکشنی رو کال بک گفتم یا برعکس یا چیزی.
باشد که اصلاح شود.

اگر دوست داشتی امتیاز دادن یادت نره!