296 lines
13 KiB
Markdown
296 lines
13 KiB
Markdown
# Edge Cases Quick Reference
|
|
|
|
> สรุปกรณีพิเศษที่ต้องระวังในระบบ E-Learning - สำหรับอ้างอิงด่วน
|
|
|
|
## 📋 สารบัญ Edge Cases
|
|
|
|
| # | Edge Case | ความเสี่ยง | แนวทางแก้ไข |
|
|
|---|-----------|-----------|-------------|
|
|
| 1 | [การเปลี่ยนบทบาทโดย Admin](#1-การเปลี่ยนบทบาทผู้ใช้) | 🟡 ปานกลาง | Invalidate sessions + audit log |
|
|
| 2 | [หลักสูตรถูกซ่อน/ลบ](#2-หลักสูตรถูกซ่อนลบ) | 🟡 ปานกลาง | Read-only mode สำหรับผู้ลงทะเบียนแล้ว |
|
|
| 3 | [ลงทะเบียนซ้ำ](#3-ลงทะเบียนซ้ำ) | 🟢 ต่ำ | ตรวจสอบและ redirect |
|
|
| 4 | [ข้ามลำดับบทเรียน](#4-ข้ามลำดับบทเรียน) | 🟡 ปานกลาง | ตรวจสอบ prerequisite |
|
|
| 5 | [ทำแบบทดสอบหลายครั้ง](#5-ทำแบบทดสอบหลายครั้ง) | 🟡 ปานกลาง | จำกัดครั้ง + cooldown |
|
|
| 6 | [แก้ไขขณะมีคนใช้งาน](#6-แก้ไขขณะมีคนใช้งาน) | 🔴 สูง | Soft delete + แจ้งเตือน |
|
|
| 7 | [ลบ Instructor ที่มีหลักสูตร](#7-ลบ-instructor-ที่มีหลักสูตร) | 🔴 สูง | บังคับโอนหลักสูตรก่อน |
|
|
| 8 | [เข้าถึงข้อมูลข้ามหลักสูตร](#8-เข้าถึงข้อมูลข้ามหลักสูตร) | 🔴 สูง | Middleware ตรวจสอบ ownership |
|
|
| 9 | [เพิ่มเนื้อหาหลังจบหลักสูตร](#9-เพิ่มเนื้อหาหลังจบหลักสูตร) | 🟡 ปานกลาง | เนื้อหาใหม่ = เสริม (ไม่บังคับ) |
|
|
| 10 | [Maintenance Mode](#10-maintenance-mode) | 🟡 ปานกลาง | Auto-save + แจ้งเตือนล่วงหน้า |
|
|
| 11 | [Video Progress Tracking](#11-video-progress-tracking) | 🟡 ปานกลาง | Save ทุก 5 วินาที + last_watched_at |
|
|
|
|
---
|
|
|
|
## 1. การเปลี่ยนบทบาทผู้ใช้
|
|
|
|
> **หมายเหตุ**: ไม่มีการเปลี่ยนบทบาทระหว่าง Student-Instructor ในการใช้งานปกติ
|
|
> เกิดขึ้นเฉพาะกรณีพิเศษที่ Admin จัดการ (เช่น แก้ไขข้อมูลผิดพลาด)
|
|
|
|
**ปัญหา**: Token/Session เก่ายังมีสิทธิ์เดิม
|
|
|
|
**วิธีแก้**:
|
|
```javascript
|
|
// Admin เปลี่ยนบทบาท (กรณีพิเศษ)
|
|
// 1. บันทึก audit log (ระบุเหตุผล)
|
|
// 2. อัปเดตบทบาท
|
|
// 3. Invalidate sessions ทั้งหมด
|
|
// 4. แจ้งเตือนผู้ใช้ทางอีเมล
|
|
// 5. บังคับ login ใหม่
|
|
```
|
|
|
|
**Key Points**:
|
|
- ✅ เฉพาะ Admin เท่านั้น
|
|
- ✅ ต้องระบุเหตุผลและบันทึก audit log
|
|
- ✅ Invalidate sessions ทันที
|
|
- ✅ แจ้งเตือนผู้ใช้ทางอีเมล
|
|
|
|
---
|
|
|
|
## 2. หลักสูตรถูกซ่อน/ลบ
|
|
|
|
**ปัญหา**: Student ที่ลงทะเบียนแล้วควรเข้าถึงได้หรือไม่?
|
|
|
|
**วิธีแก้**:
|
|
- **ซ่อน**: Student ที่ลงทะเบียนแล้ว → เข้าถึงได้ปกติ
|
|
- **ลบ**: Student ที่ลงทะเบียนแล้ว → Read-only mode
|
|
|
|
**Key Points**:
|
|
- ✅ ใช้ Soft Delete
|
|
- ✅ ใบประกาศนียบัตรที่ออกแล้วยังใช้ได้
|
|
- ❌ ห้ามทำแบบทดสอบใหม่ในหลักสูตรที่ถูกลบ
|
|
|
|
---
|
|
|
|
## 3. ลงทะเบียนซ้ำ
|
|
|
|
**ปัญหา**: ข้อมูลความคืบหน้าจะเป็นอย่างไร?
|
|
|
|
**วิธีแก้**:
|
|
```javascript
|
|
if (existingEnrollment) {
|
|
return redirect(`/courses/${courseId}`);
|
|
}
|
|
```
|
|
|
|
**Key Points**:
|
|
- ✅ ตรวจสอบก่อนสร้าง enrollment
|
|
- ✅ Redirect ไปที่หลักสูตร
|
|
- ❌ ห้ามรีเซ็ตความคืบหน้า
|
|
|
|
---
|
|
|
|
## 4. ข้ามลำดับบทเรียน
|
|
|
|
**ปัญหา**: Student ใช้ Direct URL ข้ามลำดับ
|
|
|
|
**วิธีแก้**:
|
|
```javascript
|
|
// ตรวจสอบว่าเรียน Lesson ก่อนหน้าครบหรือไม่
|
|
if (!allPreviousCompleted) {
|
|
return { access: false, nextAvailableLesson };
|
|
}
|
|
```
|
|
|
|
**Key Points**:
|
|
- ✅ ตรวจสอบที่ Backend (ห้ามพึ่ง Frontend)
|
|
- ✅ แสดง Lesson ถัดไปที่เข้าถึงได้
|
|
- ✅ รองรับหลักสูตรที่ไม่บังคับลำดับ
|
|
|
|
---
|
|
|
|
## 5. ทำแบบทดสอบหลายครั้ง
|
|
|
|
**ปัญหา**: จำกัดครั้ง? คะแนนไหนที่นับ? รอกี่นาที?
|
|
|
|
**วิธีแก้**:
|
|
```javascript
|
|
// ตรวจสอบ:
|
|
// 1. จำนวนครั้งที่ทำได้ (maxAttempts)
|
|
// 2. ระยะเวลารอ (cooldownMinutes)
|
|
// 3. นโยบายคะแนน (HIGHEST/LATEST/FIRST/AVERAGE)
|
|
```
|
|
|
|
**Key Points**:
|
|
- ✅ ใช้คะแนนสูงสุด (HIGHEST) เป็นค่าเริ่มต้น
|
|
- ✅ กำหนด cooldown ได้ต่อแบบทดสอบ
|
|
- ✅ เก็บประวัติการทำทุกครั้ง
|
|
|
|
---
|
|
|
|
## 6. แก้ไขขณะมีคนใช้งาน
|
|
|
|
**ปัญหา**: Student กำลังดู Lesson อยู่ แต่ Instructor ลบ
|
|
|
|
**วิธีแก้**:
|
|
```javascript
|
|
// ใช้ Soft Delete
|
|
if (activeViewers.length > 0) {
|
|
markAsDeleted(); // ลบถาวรใน 24 ชม.
|
|
notifyInstructor();
|
|
}
|
|
```
|
|
|
|
**Key Points**:
|
|
- ✅ ใช้ Soft Delete แทน Hard Delete
|
|
- ✅ แจ้งเตือน Instructor ว่ามีคนดูอยู่
|
|
- ✅ Student ที่เข้าถึงก่อนหน้า → ดูต่อได้
|
|
|
|
---
|
|
|
|
## 7. ลบ Instructor ที่มีหลักสูตร
|
|
|
|
**ปัญหา**: หลักสูตรจะกลายเป็น "ไม่มีเจ้าของ"
|
|
|
|
**วิธีแก้**:
|
|
```javascript
|
|
if (courses.length > 0) {
|
|
return error('กรุณาโอนหลักสูตรก่อน');
|
|
}
|
|
// ใช้ Soft Delete (deactivate)
|
|
```
|
|
|
|
**Key Points**:
|
|
- ✅ บังคับโอนหลักสูตรก่อนลบ
|
|
- ✅ ใช้ Soft Delete (deactivate)
|
|
- ✅ เก็บ Audit Log
|
|
|
|
---
|
|
|
|
## 8. เข้าถึงข้อมูลข้ามหลักสูตร
|
|
|
|
**ปัญหา**: Instructor A ดูข้อมูลหลักสูตรของ Instructor B
|
|
|
|
**วิธีแก้**:
|
|
```javascript
|
|
// Middleware ตรวจสอบ ownership
|
|
if (role === 'INSTRUCTOR' && course.instructorId !== userId) {
|
|
return 403;
|
|
}
|
|
```
|
|
|
|
**Key Points**:
|
|
- ✅ ตรวจสอบ ownership ที่ Backend
|
|
- ✅ Admin → read-only access
|
|
- ✅ Instructor → เฉพาะหลักสูตรของตนเอง
|
|
|
|
---
|
|
|
|
## 9. เพิ่มเนื้อหาหลังจบหลักสูตร
|
|
|
|
**ปัญหา**: ความคืบหน้ากลับไม่ครบ 100%
|
|
|
|
**วิธีแก้**:
|
|
```javascript
|
|
// คำนวณจากเนื้อหาตอนลงทะเบียน
|
|
if (originalProgress === 100 && certificateIssued) {
|
|
return { progress: 100, newContentAvailable: true };
|
|
}
|
|
```
|
|
|
|
**Key Points**:
|
|
- ✅ ใบประกาศนียบัตรยังใช้ได้
|
|
- ✅ เนื้อหาใหม่ = เสริม (ไม่บังคับ)
|
|
- ✅ แสดงป้าย "มีเนื้อหาใหม่"
|
|
|
|
---
|
|
|
|
## 10. Maintenance Mode
|
|
|
|
**ปัญหา**: Student กำลังทำแบบทดสอบ
|
|
|
|
**วิธีแก้**:
|
|
```javascript
|
|
// 1. แจ้งเตือนล่วงหน้า 24 ชม.
|
|
// 2. Auto-save ทุก 30 วินาที
|
|
// 3. เก็บ draft 24 ชม.
|
|
// 4. Admin เข้าถึงได้
|
|
```
|
|
|
|
**Key Points**:
|
|
- ✅ Auto-save แบบทดสอบทุก 30 วินาที
|
|
- ✅ แจ้งเตือนล่วงหน้า
|
|
- ✅ กู้คืนข้อมูลได้ภายใน 24 ชม.
|
|
|
|
---
|
|
|
|
## 11. Video Progress Tracking
|
|
|
|
**ปัญหา**: Student ดูวีดีโอค้างไว้หลายแท็บ หรือปิดเบราว์เซอร์กลางคัน
|
|
|
|
**วิธีแก้**:
|
|
```javascript
|
|
// 1. Save progress ทุก 5 วินาที
|
|
// 2. ใช้ last_watched_at เป็นตัวตัดสิน
|
|
// 3. Auto-complete เมื่อดู 90%+
|
|
// 4. Resume จากตำแหน่งล่าสุด
|
|
```
|
|
|
|
**Key Points**:
|
|
- ✅ Save progress ทุก 5 วินาที (ไม่บ่อยเกินไป)
|
|
- ✅ ใช้ `last_watched_at` ตัดสินว่า session ไหนล่าสุด
|
|
- ✅ Auto-complete เมื่อดู ≥ 90%
|
|
- ✅ Resume จากตำแหน่งที่บันทึกล่าสุด
|
|
- ❌ ไม่ save เมื่อ video pause หรือ buffering
|
|
|
|
**Concurrent Updates**:
|
|
```javascript
|
|
// แท็บ A: บันทึกที่ 5:00 (14:00:00)
|
|
// แท็บ B: บันทึกที่ 3:00 (14:00:05)
|
|
// → ใช้แท็บ B (last_watched_at ใหม่กว่า)
|
|
```
|
|
|
|
---
|
|
|
|
## 🔒 หลักการสำคัญ (Best Practices)
|
|
|
|
### 1. Soft Delete > Hard Delete
|
|
- ใช้ `isDeleted` flag แทนการลบจริง
|
|
- เก็บข้อมูลไว้สำหรับ audit trail
|
|
- ป้องกันการสูญหายของข้อมูล
|
|
|
|
### 2. Invalidate Sessions เมื่อเปลี่ยนสิทธิ์
|
|
- เปลี่ยนบทบาท → logout ทันที
|
|
- ลบบัญชี → invalidate sessions
|
|
- เปลี่ยนรหัสผ่าน → logout devices อื่น
|
|
|
|
### 3. ตรวจสอบสิทธิ์ที่ Backend เสมอ
|
|
- Frontend = UX (ซ่อน/แสดง UI)
|
|
- Backend = Security (ป้องกันการเข้าถึง)
|
|
- ห้ามพึ่งพา Frontend เพียงอย่างเดียว
|
|
|
|
### 4. Auto-save สำหรับข้อมูลสำคัญ
|
|
- แบบทดสอบ → auto-save ทุก 30 วินาที
|
|
- เนื้อหาที่กำลังเขียน → auto-save
|
|
- เก็บ draft ไว้อย่างน้อย 24 ชม.
|
|
|
|
### 5. แจ้งเตือนผู้ใช้
|
|
- Maintenance → แจ้งล่วงหน้า 24 ชม.
|
|
- ลบเนื้อหา → แจ้งว่ามีคนดูอยู่
|
|
- เปลี่ยนแปลงสำคัญ → ส่งอีเมลแจ้ง
|
|
|
|
---
|
|
|
|
## 📊 สรุปความเสี่ยงและลำดับความสำคัญ
|
|
|
|
### 🔴 ความเสี่ยงสูง (ต้องจัดการก่อน)
|
|
1. แก้ไขขณะมีคนใช้งาน
|
|
2. ลบ Instructor ที่มีหลักสูตร
|
|
3. เข้าถึงข้อมูลข้ามหลักสูตร
|
|
|
|
### 🟡 ความเสี่ยงปานกลาง
|
|
4. การเปลี่ยนบทบาทโดย Admin (กรณีพิเศษ)
|
|
5. หลักสูตรถูกซ่อน/ลบ
|
|
6. ข้ามลำดับบทเรียน
|
|
7. ทำแบบทดสอบหลายครั้ง
|
|
8. เพิ่มเนื้อหาหลังจบหลักสูตร
|
|
9. Maintenance Mode
|
|
|
|
### 🟢 ความเสี่ยงต่ำ
|
|
10. ลงทะเบียนซ้ำ
|
|
|
|
---
|
|
|
|
## 🔗 เอกสารที่เกี่ยวข้อง
|
|
|
|
- [ตารางสิทธิ์แบบเต็ม](./permissions_matrix.md)
|
|
- [User Roles and Capabilities](./user_roles_and_capabilities.md)
|
|
- [System Architecture](./elearning_architecture.md)
|