265 lines
7.7 KiB
Markdown
265 lines
7.7 KiB
Markdown
# 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`
|