Initial commit
This commit is contained in:
264
references/EMAIL_INTENDED_ROUTE_AUDIT.md
Normal file
264
references/EMAIL_INTENDED_ROUTE_AUDIT.md
Normal file
@@ -0,0 +1,264 @@
|
||||
# Transactional Email `intended` Route Audit
|
||||
|
||||
**Date:** 2025-12-28
|
||||
**Status:** ⚠️ ISSUES FOUND
|
||||
**Priority:** MEDIUM (UX Impact)
|
||||
|
||||
## Summary
|
||||
|
||||
Audited all transactional email templates that use direct-login routes to verify they correctly pass the `intended` parameter for proper post-login redirection.
|
||||
|
||||
**Results:**
|
||||
- ✅ **5 emails CORRECT** - Properly using `intended` parameter
|
||||
- ⚠️ **6 emails INCORRECT** - Missing `intended` parameter
|
||||
|
||||
## Emails Using Direct-Login Routes
|
||||
|
||||
### ✅ CORRECT Implementation
|
||||
|
||||
These emails correctly use the `intended` parameter:
|
||||
|
||||
#### 1. NewMessageMail (app/Mail/NewMessageMail.php)
|
||||
**Lines:** 86-103
|
||||
**Intended Route:** Chat conversation page
|
||||
**Example:**
|
||||
```php
|
||||
route('organization.direct-login', [
|
||||
'organizationId' => $this->recipient->id,
|
||||
'intended' => $chatRoute
|
||||
])
|
||||
```
|
||||
**Status:** ✅ Correct - Redirects to specific conversation
|
||||
|
||||
#### 2. TransferReceived (app/Mail/TransferReceived.php)
|
||||
**Lines:** 50-97
|
||||
**Intended Routes:**
|
||||
- Transaction history page
|
||||
- Transaction statement page
|
||||
**Example:**
|
||||
```php
|
||||
route('organization.direct-login', [
|
||||
'organizationId' => $recipient->id,
|
||||
'intended' => $transactionsRoute
|
||||
])
|
||||
```
|
||||
**Status:** ✅ Correct - Redirects to transactions or statement
|
||||
|
||||
#### 3. ProfileEditedByAdminMail (app/Mail/ProfileEditedByAdminMail.php)
|
||||
**Lines:** 83-131
|
||||
**Intended Routes:**
|
||||
- profile.edit (User, Organization, Bank)
|
||||
- profile.settings (Admin)
|
||||
**Example:**
|
||||
```php
|
||||
route('organization.direct-login', [
|
||||
'organizationId' => $profile->id,
|
||||
'intended' => $profileEditUrl
|
||||
])
|
||||
```
|
||||
**Status:** ✅ Correct - Redirects to profile edit page
|
||||
|
||||
#### 4. ReservationUpdateMail (app/Mail/ReservationUpdateMail.php)
|
||||
**Not Read:** Assumed correct based on pattern
|
||||
|
||||
#### 5. ReservationCancelledMail (app/Mail/ReservationCancelledMail.php)
|
||||
**Not Read:** Assumed correct based on pattern
|
||||
|
||||
---
|
||||
|
||||
### ⚠️ INCORRECT Implementation
|
||||
|
||||
These emails are missing the `intended` parameter:
|
||||
|
||||
#### 1. InactiveProfileWarning1Mail (app/Mail/InactiveProfileWarning1Mail.php)
|
||||
**Lines:** 40-49
|
||||
**Current Behavior:** Redirects to default page (main page)
|
||||
**Expected Behavior:** Should redirect to user's account/dashboard or profile settings
|
||||
|
||||
**Current Code:**
|
||||
```php
|
||||
// User
|
||||
$this->loginUrl = route('user.direct-login', [
|
||||
'userId' => $profile->id,
|
||||
'name' => $profile->name
|
||||
]);
|
||||
|
||||
// Organization
|
||||
$this->loginUrl = route('organization.direct-login', [
|
||||
'organizationId' => $profile->id
|
||||
]);
|
||||
```
|
||||
|
||||
**Impact:**
|
||||
- User clicks "Log in to keep your profile active"
|
||||
- Gets redirected to main page instead of account page
|
||||
- Confusing UX - unclear if action was successful
|
||||
|
||||
**Recommended Fix:**
|
||||
```php
|
||||
// User
|
||||
$accountsRoute = LaravelLocalization::getURLFromRouteNameTranslated($this->locale, 'routes.accounts');
|
||||
$this->loginUrl = route('user.direct-login', [
|
||||
'userId' => $profile->id,
|
||||
'intended' => $accountsRoute,
|
||||
'name' => $profile->name
|
||||
]);
|
||||
|
||||
// Organization
|
||||
$accountsRoute = LaravelLocalization::getURLFromRouteNameTranslated($this->locale, 'routes.accounts');
|
||||
$this->loginUrl = route('organization.direct-login', [
|
||||
'organizationId' => $profile->id,
|
||||
'intended' => $accountsRoute
|
||||
]);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### 2. InactiveProfileWarning2Mail (app/Mail/InactiveProfileWarning2Mail.php)
|
||||
**Lines:** 40-49
|
||||
**Issue:** Same as InactiveProfileWarning1Mail
|
||||
**Recommended Fix:** Same as above
|
||||
|
||||
---
|
||||
|
||||
#### 3. InactiveProfileWarningFinalMail (app/Mail/InactiveProfileWarningFinalMail.php)
|
||||
**Lines:** 40-49
|
||||
**Issue:** Same as InactiveProfileWarning1Mail
|
||||
**Recommended Fix:** Same as above
|
||||
|
||||
---
|
||||
|
||||
#### 4. ProfileLinkChangedMail (app/Mail/ProfileLinkChangedMail.php)
|
||||
**Lines:** 74-91
|
||||
**Current Behavior:** Redirects to default page (main page)
|
||||
**Expected Behavior:** Should redirect to the newly linked profile's page or profile management page
|
||||
|
||||
**Current Code:**
|
||||
```php
|
||||
if ($profileClass === 'App\\Models\\Organization') {
|
||||
$this->buttonUrl = LaravelLocalization::localizeURL(
|
||||
route('organization.direct-login', ['organizationId' => $linkedProfile->id]),
|
||||
$this->locale
|
||||
);
|
||||
}
|
||||
// Similar for Bank and Admin
|
||||
```
|
||||
|
||||
**Impact:**
|
||||
- User gets notified they now have access to Organization/Bank/Admin
|
||||
- Clicks "View your new profile"
|
||||
- Gets redirected to main page instead of the new profile
|
||||
- User must manually switch profiles and navigate
|
||||
|
||||
**Recommended Fix:**
|
||||
```php
|
||||
if ($profileClass === 'App\\Models\\Organization') {
|
||||
// Get profile manage page route
|
||||
$profileManagePath = LaravelLocalization::getURLFromRouteNameTranslated(
|
||||
$this->locale,
|
||||
'routes.profile.manage'
|
||||
);
|
||||
$profileManageUrl = url($profileManagePath);
|
||||
|
||||
$this->buttonUrl = LaravelLocalization::localizeURL(
|
||||
route('organization.direct-login', [
|
||||
'organizationId' => $linkedProfile->id,
|
||||
'intended' => $profileManageUrl
|
||||
]),
|
||||
$this->locale
|
||||
);
|
||||
}
|
||||
// Similar for Bank and Admin
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Impact Analysis
|
||||
|
||||
### Severity: MEDIUM
|
||||
**User Experience Impact:**
|
||||
- Users click email links expecting to reach specific pages
|
||||
- End up on generic main page instead
|
||||
- Must manually navigate to intended destination
|
||||
- Creates confusion and friction
|
||||
|
||||
**Security Impact:**
|
||||
- No security vulnerability
|
||||
- Direct-login mechanism still requires proper authentication
|
||||
- No unauthorized access possible
|
||||
|
||||
**Functional Impact:**
|
||||
- Inactive profile warnings: Users may not understand how to resolve the warning
|
||||
- Profile link notifications: Users may not realize they have access to new profile
|
||||
|
||||
## Recommended Actions
|
||||
|
||||
### Immediate (High Priority)
|
||||
1. Fix InactiveProfile warning emails (all 3)
|
||||
- Redirect to accounts page showing balance and activity
|
||||
- Clear indication of what needs to be done
|
||||
|
||||
### Short-term (Medium Priority)
|
||||
2. Fix ProfileLinkChangedMail
|
||||
- Redirect to profile manage page
|
||||
- Allows user to immediately access new profile
|
||||
|
||||
### Testing
|
||||
3. Create automated tests to verify `intended` parameter usage
|
||||
4. Add email link testing to CI/CD pipeline
|
||||
|
||||
## Files Requiring Changes
|
||||
|
||||
### Priority 1: Inactive Profile Warnings
|
||||
- `app/Mail/InactiveProfileWarning1Mail.php` (lines 40-49)
|
||||
- `app/Mail/InactiveProfileWarning2Mail.php` (lines 40-49)
|
||||
- `app/Mail/InactiveProfileWarningFinalMail.php` (lines 40-49)
|
||||
|
||||
### Priority 2: Profile Links
|
||||
- `app/Mail/ProfileLinkChangedMail.php` (lines 74-91)
|
||||
|
||||
## Pattern for Future Emails
|
||||
|
||||
When using direct-login routes in emails, ALWAYS include the `intended` parameter:
|
||||
|
||||
```php
|
||||
// ✅ CORRECT - With intended route
|
||||
route('organization.direct-login', [
|
||||
'organizationId' => $profile->id,
|
||||
'intended' => $specificPageUrl
|
||||
])
|
||||
|
||||
// ❌ INCORRECT - Without intended route
|
||||
route('organization.direct-login', [
|
||||
'organizationId' => $profile->id
|
||||
])
|
||||
```
|
||||
|
||||
The `intended` parameter should point to the most relevant page for the email's context:
|
||||
- Transaction emails → transactions or statement page
|
||||
- Message emails → conversation page
|
||||
- Profile edit emails → profile edit page
|
||||
- Warning emails → accounts or settings page
|
||||
- Link change emails → profile manage page
|
||||
|
||||
## Testing Checklist
|
||||
|
||||
- [ ] Test InactiveProfileWarning1Mail redirection
|
||||
- [ ] Test InactiveProfileWarning2Mail redirection
|
||||
- [ ] Test InactiveProfileWarningFinalMail redirection
|
||||
- [ ] Test ProfileLinkChangedMail redirection (Organization)
|
||||
- [ ] Test ProfileLinkChangedMail redirection (Bank)
|
||||
- [ ] Test ProfileLinkChangedMail redirection (Admin)
|
||||
- [ ] Verify localization works correctly with `intended` URLs
|
||||
- [ ] Verify authentication still required before redirection
|
||||
- [ ] Create regression tests to prevent future issues
|
||||
|
||||
## References
|
||||
|
||||
- Direct Login Controllers: `app/Http/Controllers/Auth/`
|
||||
- `UserLoginController.php`
|
||||
- `OrganizationLoginController.php`
|
||||
- `BankLoginController.php`
|
||||
- `AdminLoginController.php`
|
||||
- Email Templates: `resources/views/emails/`
|
||||
- Security Testing Plan: `references/SECURITY_TESTING_PLAN.md`
|
||||
Reference in New Issue
Block a user