Skip to main content

สมัครใช้งานและยืนยันอีเมล

ภาพรวม

หน้าสมัครใช้งานเป็น self-service signup ที่สร้าง organization และผู้ใช้คนแรก ขององค์กรพร้อมกันในคำขอเดียว โดยไม่ต้องรอให้ใครส่งคำเชิญ เหมาะกับลูกค้าใหม่ที่ต้องการเริ่มทดลองใช้ระบบด้วยตนเอง

เส้นทางการสมัครประกอบด้วยสองหน้า

  • /register — ฟอร์มกรอกข้อมูลองค์กรและข้อมูลผู้ใช้ พร้อมการตรวจสอบอีเมลซ้ำแบบเรียลไทม์และตัววัดความแข็งแรงของรหัสผ่าน
  • /verify-email — หน้าที่ผู้ใช้เข้ามาจากลิงก์ในอีเมล เพื่อยืนยันตัวตนด้วย token

ทั้งสองหน้าเป็นหน้าสาธารณะที่เข้าถึงได้โดยไม่ต้องมี token และแสดงผลด้วย layout แบบ authentication ที่ไม่มีแถบเมนูด้านข้างหรือแถบด้านบน

เมื่อสมัครสำเร็จ ระบบจะ ไม่ พาเข้าสู่ระบบให้อัตโนมัติ ผู้ใช้ต้องยืนยันอีเมลก่อน และองค์กรที่สร้างใหม่ยังต้องรอผู้ดูแลระบบอนุมัติจึงจะเข้าใช้งานได้จริง

Business Flow

การสมัครใช้งาน

  1. ผู้ใช้เปิดหน้า /register และกรอกข้อมูลตามฟิลด์ต่อไปนี้
    • ชื่อองค์กร (บังคับ)
    • ชื่อและนามสกุล (บังคับ)
    • อีเมล (บังคับ และต้องอยู่ในรูปแบบอีเมลที่ถูกต้อง)
    • รหัสผ่าน (บังคับ ความยาวอย่างน้อย 8 ตัวอักษร)
    • ยืนยันรหัสผ่าน (ต้องตรงกับรหัสผ่าน)
  2. ระหว่างที่ผู้ใช้พิมพ์อีเมล ระบบจะตรวจสอบความซ้ำแบบ debounce 600 มิลลิวินาที โดยเรียก GET /auth/check-email แล้วแสดงสถานะใต้ช่องกรอกเป็น กำลังตรวจสอบ / ใช้ได้ / ถูกใช้แล้ว ระบบจะเริ่มตรวจสอบก็ต่อเมื่อรูปแบบอีเมลผ่านเกณฑ์เบื้องต้นแล้วเท่านั้น
  3. ระบบคำนวณความแข็งแรงของรหัสผ่านฝั่งหน้าเว็บจากเกณฑ์ 4 ข้อ ได้แก่ ความยาวอย่างน้อย 8 ตัวอักษร มีตัวพิมพ์ใหญ่ มีตัวเลข และมีอักขระพิเศษ แล้วแสดงเป็นแถบสี 4 ระดับ (Weak / Fair / Good / Strong)
  4. เมื่อกดยืนยัน ระบบจะตรวจก่อนว่าสถานะอีเมลไม่ได้เป็น "ถูกใช้แล้ว" หากซ้ำจะแสดงข้อความผิดพลาดที่ช่องอีเมลโดยไม่ยิงคำขอไปยังเซิร์ฟเวอร์
  5. หากข้อมูลผ่านทั้งหมด ระบบส่งข้อมูลไปยัง POST /auth/register เพื่อสร้างองค์กรและผู้ใช้คนแรกในคราวเดียว
  6. เมื่อสำเร็จ หน้าจอจะเปลี่ยนจากฟอร์มเป็นหน้ายืนยันผลที่แจ้งว่าได้ส่งอีเมลไปแล้ว พร้อมลิงก์กลับไปหน้าเข้าสู่ระบบ
  7. หากไม่สำเร็จ ระบบจะแสดง modal พร้อมข้อความจากเซิร์ฟเวอร์ (กรณีที่เซิร์ฟเวอร์ส่งข้อผิดพลาดมาหลายรายการจะถูกรวมเป็นข้อความเดียว)

การยืนยันอีเมล

  1. ผู้ใช้กดลิงก์ในอีเมลซึ่งพาไปที่ /verify-email พร้อมพารามิเตอร์ token
  2. หน้าจอเรียก GET /auth/verify-email ทันทีที่เปิด และแสดงสถานะกำลังตรวจสอบระหว่างรอผล
  3. หากไม่พบ token ใน URL หน้าจอจะแสดงข้อผิดพลาดทันทีโดยไม่เรียกเซิร์ฟเวอร์
  4. สำเร็จ — แสดงสัญลักษณ์ยืนยันสีเขียวและปุ่มไปยังหน้าเข้าสู่ระบบ
  5. ไม่สำเร็จ — แสดงสัญลักษณ์แจ้งเตือนสีแดงพร้อมข้อความจากเซิร์ฟเวอร์ หรือข้อความมาตรฐานว่าลิงก์ไม่ถูกต้อง พร้อมปุ่มกลับไปหน้าสมัครใหม่
  6. เมื่อยืนยันอีเมลแล้วจึงจะเข้าสู่ระบบได้ หากองค์กรยังไม่ถูกอนุมัติ การเข้าสู่ระบบจะถูกปฏิเสธพร้อมข้อความ "รออนุมัติ"

หน้าจอและองค์ประกอบหลัก

หน้าสมัครใช้งาน

หน้า /register แยกความรับผิดชอบเป็นสองส่วน คือส่วน container ที่ดูแลตรรกะทั้งหมด (debounce ตรวจอีเมล การส่งฟอร์ม การสลับไปหน้าผลลัพธ์ และ modal แจ้งข้อผิดพลาด) และส่วนฟอร์มที่ดูแลการแสดงผล ได้แก่ ช่องกรอกข้อมูล ป้ายสถานะอีเมล และแถบวัดความแข็งแรงของรหัสผ่าน

เมื่อสมัครสำเร็จ container จะเปลี่ยนไปแสดงหน้าผลลัพธ์แทนฟอร์มเดิม โดยยังคงอยู่ที่ URL เดิม

หน้ายืนยันอีเมล

หน้า /verify-email เป็นหน้าเดียวจบที่รองรับสามสถานะ คือ กำลังตรวจสอบ สำเร็จ และผิดพลาด แต่ละสถานะมีสัญลักษณ์ ข้อความ และปุ่มดำเนินการต่อที่ต่างกัน

ชั้นบริการสำหรับการสมัคร

บริการด้านการสมัคร (src/services/registration.service.ts) รวมสามฟังก์ชันหลักไว้ด้วยกัน ได้แก่ การสมัครสมาชิก การตรวจสอบอีเมลซ้ำ และการยืนยันอีเมล

จุดที่ควรทราบคือบริการนี้ใช้ axios instance แยกของตัวเอง ไม่ผ่าน instance กลางของระบบ เพราะขั้นตอนนี้ยังไม่มี token และไม่ต้องการให้ตัวดักจับ HTTP 401 บังคับออกจากระบบโดยไม่จำเป็น

เส้นทางสาธารณะ

/register และ /verify-email ถูกกำหนดไว้ในรายการเส้นทางสาธารณะของแอปพลิเคชัน จึงเข้าถึงได้โดยไม่ต้องผ่านการตรวจสอบ token

จุดเชื่อมต่อกับฟีเจอร์อื่น

  • เข้าสู่ระบบ — เส้นทางการสมัครจบลงที่หน้า /login เสมอ และการเข้าสู่ระบบจะสำเร็จก็ต่อเมื่อยืนยันอีเมลแล้วและองค์กรถูกอนุมัติ
  • จัดการรหัสผ่าน — ใช้กลไก token ที่เข้ารหัสจากฝั่งเซิร์ฟเวอร์ในลักษณะเดียวกัน โดยมีธง isNewAccount แยกกรณีที่ผู้ใช้ตั้งรหัสผ่านครั้งแรก
  • ตั้งค่าโมดูลของ Organization — องค์กรที่สมัครเข้ามาใหม่ต้องถูกเปิดใช้งานโมดูลและกำหนดโควตาโดยผู้ดูแลระบบระดับสูงก่อนใช้งานจริง
  • ข้อควรระวังเรื่องเกณฑ์รหัสผ่าน — เกณฑ์ความแข็งแรงในหน้าสมัคร (4 ข้อ) แตกต่างจากรายการตรวจสอบ 6 ข้อที่ใช้ในหน้าตั้งรหัสผ่านใหม่และ modal เปลี่ยนรหัสผ่าน

รายละเอียดฝั่ง Backend (CMS API)

โมดูล registration ฝั่ง cms-api เป็นโมดูลที่ ไม่ใช้ route group ที่ต้องมี token เลย ทุก endpoint เป็น public เพราะขั้นตอนนี้ผู้ใช้ยังไม่มี token

Endpoint ที่หน้านี้เรียกใช้

จุดที่หน้าเว็บเรียกEndpointหมายเหตุ
ตรวจอีเมลซ้ำแบบเรียลไทม์GET /api/auth/check-emailรับอีเมลผ่าน query string
ส่งฟอร์มสมัครPOST /api/auth/registerตอบกลับสถานะ 201 เมื่อสำเร็จ
ยืนยันอีเมลจากลิงก์GET /api/auth/verify-emailรับ token ผ่าน query string

สิ่งที่ backend ทำเมื่อรับคำขอสมัคร

การเรียก POST /api/auth/register หนึ่งครั้งทำงานหลายอย่างต่อเนื่องกัน

  1. เข้ารหัสรหัสผ่านด้วย bcrypt ก่อนบันทึก — ไม่มีการเก็บรหัสผ่านแบบข้อความธรรมดาในระบบ
  2. สร้างแถวใหม่ในตาราง organization และตาราง user พร้อมผูก role เริ่มต้นของลูกค้า ให้ผู้ใช้คนแรกอัตโนมัติ ผู้ใช้จึงไม่ต้องรอให้ใครกำหนดบทบาทให้ก่อน
  3. สร้าง verification token แบบสุ่มด้วย generator ระดับ cryptographic แล้วแปลงเป็นสตริง hex
  4. ตอบกลับสถานะ 201 ซึ่งเป็นสัญญาณที่หน้าเว็บใช้สลับไปแสดงหน้าผลลัพธ์

จากนั้นระบบส่งอีเมลยืนยันออกไปผ่าน Mailer ที่แชร์ร่วมกันทั้งระบบ (ตั้งค่าจาก env กลุ่ม MAIL_SMTP_*) ไม่ได้สร้าง transport แยกต่อโมดูล

ประเด็นที่ควรรู้

  • การตรวจอีเมลซ้ำเป็นเพียงตัวช่วยฝั่ง UX ไม่ใช่การจองGET /api/auth/check-email บอกสถานะ ณ เวลาที่ถาม แต่ไม่ได้กันอีเมลไว้ให้ ระหว่างที่ผู้ใช้กรอกฟอร์มต่ออีกครึ่งนาที คนอื่นยังสมัครด้วยอีเมลนั้นได้ ดังนั้นการสมัครก็ยังอาจล้มเหลวตอนกด submit แม้ป้ายสถานะจะขึ้นว่า "ใช้ได้"
  • สมัครสำเร็จไม่ได้แปลว่าเข้าใช้งานได้ — backend สร้างองค์กรใหม่ในสถานะที่ยังใช้งานไม่ได้ การเข้าสู่ระบบจะถูกปฏิเสธจนกว่าผู้ดูแลระดับสูงจะเปิดใช้งานองค์กรและตั้งค่าโมดูล/โควตาให้ ซึ่งเป็นเหตุที่หน้า login แสดงข้อความ "รออนุมัติ" แยกจากข้อผิดพลาดทั่วไป
  • การยืนยันอีเมลเป็นการเปลี่ยนสถานะผู้ใช้เท่านั้นGET /api/auth/verify-email ทำเครื่องหมายว่าผู้ใช้ยืนยันแล้ว ไม่ได้ออก token ให้ ผู้ใช้จึงต้องกลับไปล็อกอินที่หน้า /login เองตามที่ปุ่มบนหน้ายืนยันพาไป
  • ตาราง password_history ถูกเขียนตั้งแต่ตอนสมัคร — รหัสผ่านชุดแรกถูกบันทึกลงประวัติด้วย ทำให้กลไกกันใช้รหัสผ่านซ้ำมีผลย้อนไปถึงรหัสผ่านที่ตั้งครั้งแรก
  • เกณฑ์รหัสผ่านฝั่ง backend ไม่เท่ากับตัววัดฝั่งหน้าเว็บ — แถบ Weak/Fair/Good/Strong เป็นการคำนวณของหน้าเว็บเพื่อแนะนำผู้ใช้ ส่วนกฎที่บังคับจริงคือกฎที่ backend ตรวจตอนรับคำขอ