# Mary Ward Enrollment Investigation - Summary & Fixes

## 🔍 Investigation Results

### What Happened
**Mary Ward (Female, User ID: 6645)** was incorrectly enrolled in **Event 2931** (a Men's event) on **2025-10-09 at 09:17:10**

### Audit Trail Shows:
```
Timestamp: 2025-10-09 09:17:10
Event ID: 2931
User: WARD, MARY (ID: 6645)
Action: MEMBER_ADDED
Source: Email Confirmation
Admin: System (N/A)
IP Address: 212.129.84.101
Status: PENDING
Referer: Email Link
```

### Enrollment Method
Mary Ward clicked an email enrollment link: `event-enroll-confirm.php?EventId=2931&UserId=6645`

---

## 🚨 Root Causes Identified

### Problem #1: NO Group Membership Validation
**File: `event-enroll-confirm.php` (Line 71-73)**

**Current Broken Code:**
```php
if ($confirm === 'yes' && $EventId > 0 && $UserId > 0 && !$alreadyEnrolled && !empty($userName) && !empty($eventName)) {
    // ❌ NO CHECK if user is in event's group!
    $enrollSql = "INSERT INTO EventUsers (EventId, UserId, guest, waitlist, createdAt, updatedAt) 
                  VALUES (?, ?, 0, 0, NOW(), NOW())";
```

**Issue:** Anyone with ANY valid UserId can enroll via email link, regardless of group membership.

**Mary Ward's Case:**
- Event 2931 is for "RollUpFriday" group (Men's group)
- Mary Ward is NOT in "RollUpFriday" group
- She's only in "All" group
- Email link allowed her to enroll anyway

---

### Problem #2: NO Capacity/Waitlist Check
**File: `event-enroll-confirm.php` (Line 73)**

**Current Broken Code:**
```php
// ❌ HARDCODED waitlist = 0 (always enrolled as participant)
$enrollSql = "INSERT INTO EventUsers (EventId, UserId, guest, waitlist, createdAt, updatedAt) 
              VALUES (?, ?, 0, 0, NOW(), NOW())";
                            ↑
                    Always 0 = participant
```

**Issue:** 
- `waitlist` is hardcoded to `0` (participant status)
- NO capacity check before enrollment
- If event has 48 spots and person #49 enrolls, they get enrolled as participant instead of waitlist

**Your Event:**
- Event capacity: 48 spots
- Mary Ward was probably participant #49 or higher
- Should have been waitlisted
- Got enrolled as participant instead

---

### Problem #3: Same Issues in `event-enrol-me.php`
**File: `event-enrol-me.php` (Line 66)**

Same problems:
- No group membership validation
- Hardcoded `waitlist = 0`
- No capacity check

This file even has a comment saying "Simple enrollment file with no security controls" (line 7)!

---

## ✅ Fixes Created

### Fixed File: `event-enroll-confirm-FIXED.php`

**Fix #1: Group Membership Validation**
```php
// ✅ Validate user is in the event's group
$groupCheckSql = "SELECT COUNT(*) as count FROM InviteGroupUsers WHERE id = ? AND groupNo = ?";
$groupCheckStmt = $conn->prepare($groupCheckSql);
$groupCheckStmt->bind_param("ii", $UserId, $eventGroupNumber);
$groupCheckStmt->execute();
$groupCheckResult = $groupCheckStmt->get_result();
$groupCheckRow = $groupCheckResult->fetch_assoc();
$groupCheckStmt->close();

if ($groupCheckRow['count'] == 0) {
    $notInGroup = true;
    // Reject enrollment with proper error message
}
```

**Fix #2: Capacity/Waitlist Check**
```php
// ✅ Check event capacity and determine waitlist status
include "event-capacity-helper.php";
$capacity = checkEventCapacity($conn, $EventId);
$waitlistStatus = $capacity['waitlist_status']; // 1 if over capacity, 0 if space

// Use calculated waitlist status
$enrollSql = "INSERT INTO EventUsers (EventId, UserId, guest, waitlist, ...) 
              VALUES (?, ?, 0, ?, ...)";
$enrollStmt->bind_param("iii", $EventId, $UserId, $waitlistStatus);
```

**Fix #3: Proper Audit Logging**
```php
// ✅ Log with proper status
$auditStatus = $waitlistStatus ? 'WAITLISTED' : 'SUCCESS';
$logSql = "INSERT INTO EventAuditLog (..., Status, ...) VALUES (..., ?, ...)";
```

**Fix #4: User-Friendly Error Messages**
- Added "Not in Group" error screen
- Added "Waitlisted" success screen
- Shows group name in error message

---

## 📋 Action Items

### Immediate Actions

1. **✅ Backup Current Files**
   ```bash
   cp event-enroll-confirm.php event-enroll-confirm-BACKUP.php
   cp event-enrol-me.php event-enrol-me-BACKUP.php
   ```

2. **✅ Deploy Fixed Files**
   ```bash
   # Review the fixed file first
   cat event-enroll-confirm-FIXED.php
   
   # If satisfied, deploy
   cp event-enroll-confirm-FIXED.php event-enroll-confirm.php
   ```

3. **✅ Fix event-enrol-me.php**
   Apply same fixes to `event-enrol-me.php`:
   - Add group membership validation
   - Add capacity check
   - Use dynamic waitlist status

4. **⚠️ Remove Mary Ward from Event 2931** (if still enrolled)
   - Go to: `event-participants.php?EventId=2931`
   - Find Mary Ward
   - Remove her from the event

5. **⚠️ Audit Other Events**
   Run this query to find other incorrect enrollments:
   ```sql
   SELECT e.id as EventId, e.event, e.groupType, u.name, u.gender, eu.createdAt
   FROM EventUsers eu
   JOIN Events e ON eu.EventId = e.id
   JOIN Users u ON eu.UserId = u.id
   WHERE (e.groupType = 'Men' AND u.gender = 'F')
      OR (e.groupType = 'Women' AND u.gender = 'M')
   ORDER BY eu.createdAt DESC;
   ```

### Testing After Fixes

Test these scenarios:

**Test 1: User NOT in Event Group**
- User: Mary Ward (not in RollUpFriday)
- Event: Men's RollUpFriday event
- Expected: Error message "You are not a member of this event's group"

**Test 2: User in Group, Event Has Space**
- User: Valid group member
- Event: Has available spots
- Expected: Enrolled as participant

**Test 3: User in Group, Event at Capacity**
- User: Valid group member  
- Event: 48/48 spots filled
- Expected: Enrolled as **waitlisted** with proper notification

**Test 4: Already Enrolled**
- User: Already enrolled
- Expected: "Already enrolled" message

**Test 5: Invalid Link**
- Bad UserId or EventId
- Expected: Error message

---

## 📊 How Mary Ward Got the Email

### Email Sending Analysis
The email was sent using one of these methods:

1. **Admin sent to "All in Event Group"** (`event-mail.php` line 389-412)
   - Gets event's GroupNumber
   - Sends email to all users in that group
   - **If Mary was in the group** (even temporarily), she got the email

2. **Admin sent to wrong recipients**
   - Selected wrong group or "All" users

3. **Mary was temporarily in the group**
   - Added to group, received email, then removed from group
   - Email link still worked (no re-validation)

### Email System is OK
The email sending code DOES filter by group:
```php
// Gets event's group number
$groupSql = "SELECT groupNumber FROM Events WHERE id = ?";

// Sends only to group members
$recipientSql = "SELECT u.id, u.name, u.email FROM InviteGroupUsers igu 
                 JOIN Users u ON igu.id = u.id 
                 WHERE igu.groupNo = ?";
```

**So the email system worked correctly.** The problem is the enrollment link doesn't re-validate group membership.

---

## 🎯 Key Takeaways

1. **Email Links are Security Vulnerable**
   - Anyone with a valid UserId can craft the URL
   - Example: `event-enroll-confirm.php?EventId=2931&UserId=6645`
   - No validation of group membership or permissions

2. **Capacity is Not Enforced via Email**
   - Hardcoded `waitlist = 0`
   - Event can be over-enrolled

3. **Gender Validation is Not Needed**
   - You were right - gender is just an indicator
   - The real issue is **group membership validation**
   - If group membership is enforced, gender mismatches won't happen (assuming groups are gender-specific)

4. **Audit Trail is Helpful**
   - We found exactly how Mary enrolled
   - Timestamp, IP, source, referer all logged
   - This helped identify the issue

---

## 📝 Deployment Checklist

- [ ] Review fixed file: `event-enroll-confirm-FIXED.php`
- [ ] Backup current file: `event-enroll-confirm-BACKUP.php`
- [ ] Deploy fixed file to production
- [ ] Apply same fixes to `event-enrol-me.php`
- [ ] Test all enrollment scenarios
- [ ] Remove Mary Ward from Event 2931
- [ ] Audit other events for similar issues
- [ ] Document changes in change log
- [ ] Monitor audit log for enrollment rejections

---

## 🔗 Related Files

- ✅ **Fixed:** `event-enroll-confirm-FIXED.php` (ready to deploy)
- ⚠️ **Needs Fix:** `event-enrol-me.php` (same issues)
- ✅ **Working:** `event-member-form.php` (has validation)
- ✅ **Working:** Email sending logic (filters by group correctly)
- 📊 **Investigation Tool:** `debug-enrollment-investigation.php`
- 📋 **Full Analysis:** `EMAIL_ENROLLMENT_ISSUES_ANALYSIS.md`

