Skip to main content

จัดการรหัสผ่าน (ลืม / รีเซ็ต / เปลี่ยน)

ภาพรวม

feature นี้ครอบคลุมทุกเส้นทางที่เกี่ยวข้องกับรหัสผ่านของผู้ใช้ CMS ได้แก่ ลืมรหัสผ่านและส่งอีเมลลิงก์รีเซ็ต, ตรวจสอบว่าโค้ดรีเซ็ตยังใช้ได้อยู่หรือไม่, ตั้งรหัสผ่านใหม่ และเปลี่ยนรหัสผ่านขณะที่ยังล็อกอินอยู่ พร้อมกลไก password history ที่ป้องกันการนำรหัสผ่านเดิมกลับมาใช้ซ้ำ

route ทั้งหมดอยู่ใต้ /api/user/... แต่ โค้ดอยู่ในโมดูล auth ไม่ใช่โมดูล user เนื่องจากตอน port มาจาก NestJS เส้นทางเกี่ยวกับรหัสผ่านถูกยกมาพร้อมกับ auth ทั้งชุด ส่วน internal/modules/passwordhistory เป็น port แบบหนึ่งต่อหนึ่งที่แยกออกมาเป็น standalone เพื่อให้โมดูลอื่น เช่น user และ registration เรียกใช้ได้

Business Flow

ลืมรหัสผ่าน

  1. เรียก POST /api/user/forgot-password พร้อม body ที่มีฟิลด์ email โดยจำกัด 3 ครั้งต่อ 10 วินาที
  2. ระบบสร้างโค้ดสุ่มความยาว 16 ตัวอักษรแบบ hex จาก crypto/rand ขนาด 8 bytes แล้วบันทึกแถวลงตาราง forgot_password พร้อมกำหนด expired_date เป็นเวลาปัจจุบันบวกหนึ่งวัน โดยตัดเศษวินาทีทิ้งเพื่อให้ตรงกับพฤติกรรมของโค้ด JavaScript เดิม
  3. ส่งอีเมลผ่าน Mailer โดยจัดรูปแบบเวลาหมดอายุเป็นโซนเวลา Asia/Bangkok ตัวอย่างข้อความคือ Please reset your password by July 5, 2026 on 5:33 PM (UTC+7).
  4. หากค้นหาผู้ใช้จากอีเมลไม่พบ ระบบตอบ error AUT_101 (Not found user for reset password)

ตรวจสอบโค้ดและตั้งรหัสผ่านใหม่

  1. GET /api/user/reset-password/:code — cms-web เรียกตอนเปิดหน้าจากลิงก์ในอีเมล เพื่อตรวจว่าโค้ดยังไม่หมดอายุและยังไม่ถูกใช้งาน
  2. POST /api/user/reset-password พร้อมโค้ดและรหัสผ่านใหม่ ระบบจะ hash ด้วย bcrypt แล้วอัปเดตฟิลด์ user.password บันทึกลง password_history และทำเครื่องหมายว่าโค้ดนั้นถูกใช้แล้ว

เปลี่ยนรหัสผ่านขณะล็อกอินอยู่

  1. POST /api/user/change-password ต้องผ่าน JwtAuth และจำกัด 5 ครั้งต่อ 60 วินาที โดยระบบจะตรวจรหัสผ่านเดิม ตรวจว่ารหัสใหม่ไม่ซ้ำกับประวัติ แล้วจึงอัปเดตและบันทึกประวัติเพิ่ม

ไฟล์และฟังก์ชันหลัก

โค้ดหลักอยู่ที่ internal/modules/auth/password.go, internal/modules/auth/hash.go และ internal/modules/auth/controller.go สำหรับการ register route ส่วน internal/modules/passwordhistory/service.go เป็น port แบบ standalone และ internal/modules/user/service.go ให้ createForgotPassword กับ getExpiredDateText

MethodRouteHandlerThrottle
POST/api/user/forgot-passwordm.forgotPassword3 ครั้ง / 10 วินาที
POST/api/user/reset-passwordm.resetPassword3 ครั้ง / 10 วินาที
GET/api/user/reset-password/:codem.resetPasswordCheckCode3 ครั้ง / 10 วินาที
POST/api/user/change-passwordm.changePassword5 ครั้ง / 60 วินาที และต้องผ่าน JwtAuth

หมายเหตุ: internal/modules/passwordhistory/controller.go มี RegisterRoutes ที่ว่างเปล่าโดยเจตนา เนื่องจาก controller ใน NestJS เดิมก็ว่างเช่นกัน โมดูลนี้จึงเป็น provider-only

จุดเชื่อมต่อกับ Service อื่น

  • Permission — ไม่ต้องมีสิทธิ์ใด ๆ เพราะเป็น public ยกเว้น change-password ที่ต้องผ่าน JwtAuth
  • ตารางuser, forgot_password และ password_history
  • Mailerinternal/mail/mail.go ตั้งค่าจาก environment กลุ่ม MAIL_SMTP_*
  • Hashing — bcrypt จาก golang.org/x/crypto/bcrypt
  • Throttleinternal/core/middleware/throttle.go ผ่าน middleware.Throttle(limit, ttlMs)
  • เอกสารที่เกี่ยวข้อง — การเข้าสู่ระบบและ JWT, User Management และ สมัครใช้งาน