Skip to main content

จัดการผู้ใช้ บทบาท และสิทธิ์

ภาพรวม​

ฟีเจอร์นี้ประกอบด้วยสองส่วนที่ทำงานร่วมกัน

  • การจัดการผู้ใช้ ที่ /user-management — สร้าง แก้ไข ดูรายละเอียด และลบผู้ใช้ กำหนดบทบาท เปิดปิดสถานะ ระบุว่าผู้ใช้เข้าถึง LINE OA ใดได้บ้าง และสั่งรีเซ็ตรหัสผ่านแทนผู้ใช้
  • ระบบสิทธิ์ — กลไกที่แปลงสิทธิ์ซึ่งเซิร์ฟเวอร์ส่งมา ให้กลายเป็นกฎที่หน้าเว็บใช้ควบคุมการเข้าถึงหน้า เมนู และปุ่มบางจุด

ผู้ใช้ในระบบนี้เป็นข้อมูลระดับองค์กร ไม่ได้ผูกกับ channel ใด channel หนึ่ง หน้านี้จึงถูกจัดเป็นหน้าระดับบัญชีเช่นเดียวกับหน้าจัดการ LINE OA และแสดงผลใน layout ที่ไม่มีเมนูด้านข้าง

จุดที่ควรทราบคือหน้านี้ ไม่ปรากฏในเมนูด้านข้าง ผู้ใช้เข้าถึงได้สองทางเท่านั้น คือปุ่มบนส่วนหัวของหน้าจัดการ LINE OA และเมนูลัด (quick access) โดยทั้งสองทางถูกกรองด้วยสิทธิ์การดูข้อมูลผู้ใช้ ตัวหน้าเองก็มีการตรวจสิทธิ์ระดับ route ครอบไว้อีกชั้นทั้งหน้ารายการและหน้าฟอร์ม

Business Flow​

1. รายการผู้ใช้​

  1. เมื่อเปิดหน้า ระบบตรวจสิทธิ์การดูข้อมูลผู้ใช้ก่อน แล้วตั้งค่า breadcrumb และเมนูที่กำลังใช้งาน
  2. ระบบโหลดเงื่อนไขการค้นหาล่าสุดจาก sessionStorage แล้วดึงข้อมูลจาก GET /user
  3. แถบเครื่องมือประกอบด้วยช่องค้นหา ตัวกรองสถานะ และตัวเลขจำนวนผู้ใช้ทั้งหมด
  4. ตารางแสดง 5 คอลัมน์ ได้แก่ ลำดับ ข้อมูลผู้ใช้ (รูปย่อ ชื่อเต็มที่คลิกเข้าดูรายละเอียดได้ และอีเมล) บทบาท สถานะ และปุ่มดำเนินการ
  5. ป้ายบทบาทถูกกำหนดสีอัตโนมัติจากชื่อบทบาท เช่น กลุ่มผู้ดูแลระบบเป็นสีแดง ผู้จัดการเป็นสีส้ม และผู้แก้ไขเป็นสีฟ้า
  6. คอลัมน์ดำเนินการมี 4 ปุ่ม คือ แก้ไข กำหนดสิทธิ์เข้าถึง OA รีเซ็ตรหัสผ่าน และลบ
  7. ทุกครั้งที่เปลี่ยนหน้า จำนวนต่อหน้า หรือเงื่อนไขการค้นหา ระบบจะบันทึกลง sessionStorage
  8. ปุ่มสร้างผู้ใช้อยู่ที่ส่วนหัวของหน้า

2. สร้าง แก้ไข และดูข้อมูลผู้ใช้​

  1. หน้าฟอร์มรองรับสามโหมด คือ สร้างใหม่ แก้ไข และดูอย่างเดียว โดยแยกจากพารามิเตอร์ใน URL
  2. ระบบโหลดรายการบทบาทสำหรับ dropdown และโหลดข้อมูลผู้ใช้ในกรณีที่มีรหัสผู้ใช้
  3. ฟอร์มมี 5 ฟิลด์ ได้แก่ ชื่อ นามสกุล อีเมล บทบาท และสถานะ (ใช้งาน / ปิดใช้งาน)
  4. ในโหมดแก้ไข อีเมลและบทบาทถูกล็อกไว้ ไม่สามารถเปลี่ยนได้ ส่วนโหมดดูอย่างเดียวจะปิดทุกฟิลด์และแสดงเพียงปุ่มย้อนกลับ
  5. เมื่อบันทึก ระบบส่งข้อมูลไปยัง POST /user สำหรับการสร้าง หรือ PUT /user/{id} สำหรับการแก้ไข
  6. เมื่อสำเร็จจะแสดงข้อความยืนยันและกลับไปหน้ารายการ หากเซิร์ฟเวอร์ระบุฟิลด์ที่ผิดพลาด ระบบจะแสดงข้อความรายฟิลด์ มิฉะนั้นจะเปิด modal แจ้งข้อผิดพลาด

3. ลบผู้ใช้​

ปุ่มลบในตารางเปิดกล่องยืนยันแบบ inline เมื่อยืนยันแล้วระบบเรียก DELETE /user/{id} และโหลดตารางใหม่

4. รีเซ็ตรหัสผ่านแทนผู้ใช้​

ปุ่มรูปกุญแจเปิดกล่องยืนยัน เมื่อยืนยันแล้วระบบเรียก POST /user/{id}/admin-reset-password จากนั้นเซิร์ฟเวอร์จะส่งอีเมลลิงก์ตั้งรหัสผ่านใหม่ให้ผู้ใช้รายนั้น รายละเอียดของขั้นตอนต่อจากนั้นอยู่ในหัวข้อจัดการรหัสผ่าน

5. กำหนดสิทธิ์เข้าถึง LINE OA ของผู้ใช้​

  1. ปุ่มกำหนดสิทธิ์ในตารางเปิด modal ที่ดึงข้อมูลจาก GET /user/{id}/oa-access
  2. ระบบเลือกโหมดให้อัตโนมัติ หากผู้ใช้เคยถูกกำหนด OA เจาะจงไว้จะเริ่มที่โหมด "เฉพาะบาง OA" มิฉะนั้นจะเป็นโหมด "ทุก OA"
  3. ในโหมดเฉพาะบาง OA ระบบแสดงรายชื่อ channel ทั้งหมดให้ติ๊กเลือก
  4. หากเลือกโหมดเฉพาะบาง OA แต่ไม่ได้ติ๊กเลย ระบบจะแจ้งเตือนและไม่บันทึก
  5. เมื่อบันทึก ระบบส่งรายการ OA ไปยัง PUT /user/{id}/oa-access โดยการส่งรายการว่างมีความหมายว่า เข้าถึงได้ทุก channel
  6. มุมกลับของการตั้งค่านี้คือ modal จัดการสิทธิ์เข้าถึงในหน้าจัดการ LINE OA ซึ่งมองจากฝั่ง channel

6. การแปลงสิทธิ์จากเซิร์ฟเวอร์มาเป็นกฎฝั่งหน้าเว็บ​

  1. เซิร์ฟเวอร์ส่งสิทธิ์มาเป็นรายการของโมดูลพร้อมชุดการกระทำที่อนุญาต เช่น อ่าน สร้าง แก้ไข ลบ และส่งออก
  2. ระบบแปลงข้อมูลนี้ในสามขั้น
    • ค้นหาว่าชื่อโมดูลฝั่งเซิร์ฟเวอร์ตรงกับหน้าใดในหน้าเว็บ โมดูลที่ไม่มีหน้ารองรับจะถูกข้ามไป
    • แปลงชุดการกระทำ โดยการกระทำกลุ่มอ่านจะถูกแปลงเป็นสิทธิ์ "ดู" และการส่งออกจะถูกแปลงเป็นสิทธิ์ "ส่งออก" ส่วนสร้าง แก้ไข และลบ ไม่ถูกแปลง เข้าสู่ระบบสิทธิ์ฝั่งหน้าเว็บ
    • โมดูลหนึ่งของเซิร์ฟเวอร์อาจปลดล็อกหลายหน้าในหน้าเว็บพร้อมกัน
  3. กฎที่ได้ถูกประกอบเป็นชุดกฎแบบอนุญาตล้วน ไม่มีการปฏิเสธเฉพาะเจาะจงและไม่มีเงื่อนไขระดับข้อมูล
  4. ชุดกฎถูกเก็บใน state ส่วนกลางแต่ ไม่ถูก persist จึงต้องคำนวณใหม่ทุกครั้งที่โหลดหน้า จุดที่คำนวณมีสองแห่งคือตอนโหลดแอปพลิเคชัน และตอนเลือก channel เพื่อเข้าใช้งาน

ตารางการแปลงชื่อโมดูลของเซิร์ฟเวอร์ไปเป็นหน้าในหน้าเว็บ

โมดูลฝั่งเซิร์ฟเวอร์หน้าที่ถูกปลดล็อก
dashboardแดชบอร์ด
line-oaจัดการ LINE OA, เมนูบิลเดอร์ และกลุ่มหน้าจัดการเนื้อหาทั้งหมด
userจัดการผู้ใช้ และหน้าตั้งค่า
rich-menuริชเมนูทั้งสามประเภท (default, custom, switch)
rich-messageจัดการ Rich Message
template-messageจัดการ Template Message
campaignจัดการแคมเปญ และปฏิทินวางแผนแคมเปญ
auto-responseตอบกลับอัตโนมัติ และ Quick Reply
report-all-friendsรายงานเพื่อนทั้งหมด
audiencesจัดการกลุ่มเป้าหมายทุกรูปแบบ
form-builderตัวสร้างฟอร์ม และการตั้งค่า OTP
customer-databaseฐานข้อมูลสมาชิก
import-mappingการจับคู่ข้อมูลนำเข้า
attribute-masterการตั้งค่าแอตทริบิวต์
trigger-ruleกฎทริกเกอร์
workflowเวิร์กโฟลว์
friend-trackการติดตามเพื่อน
api-keyจัดการ API Key
system-attributeหน้าตั้งค่า
system_moduleฐานความรู้ และการซิงก์ BigQuery

7. การนำสิทธิ์ไปใช้กรองส่วนติดต่อผู้ใช้​

  • ระดับหน้า — คอมโพเนนต์ครอบหน้า (PermissionGuard) จะไม่แสดงอะไรเลยระหว่างที่สิทธิ์ยังโหลดไม่เสร็จ แสดงหน้าแจ้งไม่มีสิทธิ์เมื่อไม่ผ่านเงื่อนไข และแสดงเนื้อหาจริงเมื่อผ่าน
  • เมนูด้านข้าง — แต่ละรายการเมนูถูกเพิ่มเข้าไปก็ต่อเมื่อผู้ใช้มีสิทธิ์ดูหน้านั้น เมนูริชเมนูจะตรวจสิทธิ์รวมของทั้งสามประเภทก่อน แล้วจึงกรองเมนูย่อยแต่ละตัว ส่วนกลุ่มเมนู Apps และ Settings ถูกแสดงโดยไม่ตรวจสิทธิ์ ยกเว้นเมนูย่อยการตั้งค่า OTP
  • เมนูลัด — รายการที่ไม่ระบุหน้าอ้างอิงจะแสดงเสมอ ส่วนรายการที่ระบุจะถูกกรองด้วยสิทธิ์เช่นเดียวกับเมนูด้านข้าง
  • ระดับปุ่ม — มีการใช้กรองปุ่มเพียงไม่กี่จุด เช่น ปุ่มเข้าหน้าจัดการผู้ใช้บนหน้าจัดการ LINE OA
  • ข้อจำกัดที่ควรทราบ — เนื่องจากการกระทำสร้าง แก้ไข และลบไม่ถูกแปลงเข้าสู่ระบบสิทธิ์ฝั่งหน้าเว็บ ปุ่มเหล่านี้จึงแสดงกับทุกคนที่เข้าถึงหน้านั้นได้ การควบคุมที่แท้จริงจึงอยู่ที่ฝั่งเซิร์ฟเวอร์
  • สิทธิ์ super admin — การจัดการสิทธิ์เข้าถึง channel รายผู้ใช้ในหน้าจัดการ LINE OA ตรวจจากรหัสบทบาทโดยตรง ไม่ได้ผ่านระบบสิทธิ์กลาง

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

หน้ารายการผู้ใช้​

ตรรกะทั้งหมดของหน้ารายการรวมอยู่ในตัวควบคุมเดียว (src/components/user-management/list/user-management.container.tsx) ซึ่งสร้างทั้งตาราง แถบเครื่องมือ และคอลัมน์ขึ้นเองภายในไฟล์ พร้อมจัดการการลบ การรีเซ็ตรหัสผ่าน และการค้นหา

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

หน้าฟอร์มผู้ใช้​

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

ชั้นระบบสิทธิ์​

ระบบสิทธิ์อยู่ในโฟลเดอร์ src/components/ability/ แยกเป็นสองไฟล์หลัก คือไฟล์ตารางการแปลงชื่อโมดูลกับฟังก์ชันแปลงข้อมูล และไฟล์ที่ประกอบกฎขึ้นเป็นชุดสิทธิ์ที่ใช้งานได้จริง

ปลายทาง API หลัก​

การทำงานปลายทาง
รายการผู้ใช้GET /user
ข้อมูลผู้ใช้รายคนGET /user/{id}
สร้างผู้ใช้POST /user
แก้ไขผู้ใช้PUT /user/{id}
ลบผู้ใช้DELETE /user/{id}
สิทธิ์เข้าถึง OA ของผู้ใช้GET และ PUT /user/{id}/oa-access
รีเซ็ตรหัสผ่านโดยผู้ดูแลระบบPOST /user/{id}/admin-reset-password
โหลดสิทธิ์เพื่อสร้างชุดกฎGET /user/{id}/permission
รายการบทบาทสำหรับ dropdownGET /system-role/find-all-object

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

  • เข้าสู่ระบบ — ชุดกฎสิทธิ์ถูกสร้างขึ้นตอนโหลดแอปพลิเคชันและตอนเลือก channel รวมถึงการเปิดสิทธิ์เข้าหน้าเลือก OA ไว้ก่อนเสมอ
  • จัดการ LINE OA — เป็นทางเข้าหลักของหน้านี้ และมี modal จัดการสิทธิ์เข้าถึงที่เป็นมุมกลับของการตั้งค่า OA access
  • จัดการรหัสผ่าน — ปุ่มรีเซ็ตรหัสผ่านในตารางเป็นจุดเริ่มต้นของเส้นทางส่งลิงก์ตั้งรหัสผ่านใหม่ให้ผู้ใช้
  • การกำหนดสิทธิ์ของบทบาท — CMS นี้ไม่มีหน้าจัดการบทบาทและสิทธิ์ การกำหนดว่าบทบาทใดเข้าถึงโมดูลใดได้ทำที่ฝั่งเซิร์ฟเวอร์
  • ทุกหน้าในระบบ — ระบบสิทธิ์ที่อธิบายในหน้านี้เป็นตัวกำหนดว่าผู้ใช้แต่ละคนจะเห็นเมนูและเข้าถึงหน้าใดได้บ้าง

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

หัวข้อนี้สำคัญเป็นพิเศษ เพราะระบบสิทธิ์ฝั่ง backend ไม่ได้ทำงานอย่างที่ชื่อบอก และการเข้าใจผิดตรงนี้นำไปสู่การประเมินความปลอดภัยที่คลาดเคลื่อนได้ง่าย

ระบบสิทธิ์มี 4 ชั้น และบังคับใช้จริงเพียง 3 ชั้น​

ชั้นบังคับใช้จริงหรือไม่ทำอะไร
CASL policy (สิทธิ์ระดับ action/module)ไม่บังคับมีข้อมูลกำกับครบทุกเส้นทาง แต่ตัวตรวจสอบถูกทำให้ปล่อยผ่านทุกคำขอ
SuperAdminGuardบังคับจริงต้องมีรหัสบทบาทเท่ากับ 1
ModuleGateบังคับจริงถ้าผู้ดูแลระดับแพลตฟอร์มปิดโมดูลของ organization ไว้ ลูกค้าจะได้ 403 แม้ยิง API ตรง
AppEnabledGuardบังคับจริงapp (นัดหมาย / loyalty / bulletin) ต้องถูกเปิดให้องค์กรนั้นก่อน

ข้อสรุปที่ต้องจำ: สิทธิ์ในตารางบทบาทและโมดูลถูกใช้เพียงเพื่อซ่อน/แสดงเมนูใน cms-web เท่านั้น ไม่ได้ปิดกั้นการเรียก API — พฤติกรรมนี้ถูกยกมาจากระบบเวอร์ชันก่อนหน้าโดยตั้งใจ (ตัวตรวจ policy เดิมก็คืนค่าอนุญาตตลอดเช่นกัน) ข้อสังเกตในหน้านี้ที่ว่า "การควบคุมที่แท้จริงอยู่ที่ฝั่งเซิร์ฟเวอร์" จึงต้องเข้าใจให้ตรงว่าหมายถึง ModuleGate และ SuperAdminGuard ไม่ใช่สิทธิ์รายการกระทำ

สิ่งที่ GET /api/user/:id/permission ทำจริง​

  1. บังคับให้อ่านได้เฉพาะของตัวเอง — รหัสผู้ใช้ใน path ต้องตรงกับผู้ใช้ที่ถือ token ถ้าไม่ตรงจะถูกปฏิเสธด้วยข้อความว่าเข้าถึงรหัสผู้ใช้อื่นไม่ได้ ดังนั้นหน้าเว็บจึงเรียกดูสิทธิ์ของคนอื่นไม่ได้เลย
  2. โหลด baseline ของผู้ใช้จากสิทธิ์ที่ผูกกับบทบาท แล้วดึงรายชื่อโมดูลทั้งหมดในระบบมาประกอบ
  3. ตัดสินด้วยประเภทของผู้ใช้ — ถ้าเป็นผู้ใช้ประเภทลูกค้าและองค์กรนั้นมีการตั้งค่าโมดูลระดับองค์กรไว้ จะใช้ค่าที่ผู้ดูแลแพลตฟอร์มกำหนดแทน baseline ของบทบาท แต่ถ้าเป็นผู้ใช้ประเภทผู้ดำเนินการแพลตฟอร์ม (รวมบทบาทรหัส 1) จะใช้ baseline ตามบทบาทเสมอ ไม่ถูก override
  4. ตอบกลับเป็นรายการที่จับคู่ชื่อโมดูลกับชุดการกระทำ ให้หน้าเว็บนำไปแปลงเป็นชุดกฎ

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

ModuleGate — ชั้นที่ปิดกั้นจริงที่ระดับ API​

Gate นี้ทำงานตามลำดับ: อ่านประเภทของผู้เรียกจาก context → ถ้าเป็นผู้ดำเนินการแพลตฟอร์ม (หรือระบุตัวไม่ได้) จะปล่อยผ่านทันที → ถ้าเป็นลูกค้าจึงตรวจว่าโมดูลนั้นเปิดให้องค์กรหรือไม่ ด้วยตรรกะ baseline-กับ-override ชุดเดียวกับข้างบน

จุดที่ควรรู้เรื่องพฤติกรรมเมื่อเกิดข้อผิดพลาด:

  • ModuleGate ออกแบบให้ fail open — ถ้าการตรวจสอบล้มเหลว (เช่น query สะดุด) ระบบจะปล่อยผ่านพร้อมบันทึก log แทนที่จะปฏิเสธ เพื่อไม่ให้ทั้งองค์กรถูกล็อกออกจากระบบเพราะปัญหาชั่วคราว
  • ตรงข้ามกับเส้นทางเฉพาะแพลตฟอร์มที่ fail closed — เส้นทางเปิด/ปิด app ให้องค์กรจะปฏิเสธไว้ก่อนเมื่อตรวจไม่ได้ เพราะความเสี่ยงคือการยกระดับสิทธิ์

โมดูลที่ถูกครอบด้วย ModuleGate ได้แก่ api-key, attribute-master, audiences, auto-response, campaign, customer-database, form-builder, friend-track, import-mapping, report-all-friends, rich-menu, rich-message, template-message, trigger-rule และ workflow

รายละเอียดของโมดูล user​

  • ทุกเส้นทางใช้ guard แบบยอมรับ token ที่ยังไม่มีรหัส OA ไม่ใช่ guard ปกติ เพราะหน้าจัดการผู้ใช้เป็นหน้าระดับบัญชีที่ต้องเข้าถึงได้โดยไม่ต้องเลือก channel ก่อน
  • รายการผู้ใช้ถูกจำกัดขอบเขตตามองค์กรของผู้เรียกเสมอ ผู้ดูแลขององค์กรหนึ่งจึงไม่เห็นผู้ใช้ขององค์กรอื่นแม้ชั้น policy จะไม่บังคับ
  • การสร้างผู้ใช้รับข้อมูลแบบ multipart เพื่อรองรับการอัปโหลดรูปโปรไฟล์ พร้อมเข้ารหัสรหัสผ่านและบันทึกลงประวัติรหัสผ่านไปในคำขอเดียว
  • การลบเป็น soft delete โดยประทับเวลาที่ลบไว้ ส่วนการลบจริงมีเส้นทางแยกที่ต้องเป็น super admin และต้องส่งพารามิเตอร์ยืนยัน — หน้าเว็บไม่มีปุ่มเรียกเส้นทางนี้
  • สิทธิ์เข้าถึง OA รายคน เขียนลงตารางเดียวกับ modal ในหน้าจัดการ LINE OA จึงเป็นข้อมูลชุดเดียวกันที่มองจากคนละมุมจริง ๆ ฟีเจอร์นี้เป็นของใหม่ที่ไม่มีในระบบเวอร์ชันก่อนหน้า
  • GET /api/user/find-all-object ที่ใช้ทำ dropdown ไม่มีข้อมูลกำกับสิทธิ์เลย ตามที่ระบบเดิมเคยคอมเมนต์ไว้

รายละเอียดของบทบาท (System Role)​

  • โมดูลบทบาทฝั่ง backend เปิดเพียง endpoint เดียว คือ GET /api/system-role/find-all-object สำหรับทำ dropdown เท่านั้น
  • ไม่มี API สำหรับแก้ไขบทบาทหรือสิทธิ์ของบทบาท — ข้อมูลเหล่านี้เป็นข้อมูล master ที่ตั้งไว้ในฐานข้อมูลโดยตรง แล้วปรับต่อรายองค์กรผ่านการตั้งค่าโมดูลของ organization นี่คือคำอธิบายเชิงเทคนิคของข้อสังเกตที่ว่า CMS ไม่มีหน้าจัดการบทบาท
  • บทบาทรหัส 1 คือ super admin ซึ่งเป็นค่าที่ guard ระดับ super admin ตรวจโดยตรง สอดคล้องกับที่หน้าเว็บตรวจรหัสบทบาทเองแทนการผ่านระบบสิทธิ์กลาง