Initial commit
This commit is contained in:
193
app/Http/Requests/ProfileEmailVerificationRequest.php
Normal file
193
app/Http/Requests/ProfileEmailVerificationRequest.php
Normal file
@@ -0,0 +1,193 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Requests;
|
||||
|
||||
use App\Events\ProfileVerified;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Validation\Validator;
|
||||
|
||||
class ProfileEmailVerificationRequest extends FormRequest
|
||||
{
|
||||
public $profileModel;
|
||||
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize()
|
||||
{
|
||||
$type = $this->route('type');
|
||||
$profileId = $this->route('id');
|
||||
$modelClass = 'App\\Models\\' . \Illuminate\Support\Str::studly($type);
|
||||
|
||||
if (!class_exists($modelClass)) {
|
||||
Log::warning("Authorization failed: Model class does not exist - {$modelClass}");
|
||||
return false;
|
||||
}
|
||||
|
||||
$profileModel = $modelClass::find($profileId);
|
||||
if (!$profileModel) {
|
||||
Log::warning("Authorization failed: Profile model not found - {$modelClass} with ID {$profileId}");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check all guards to find authenticated user
|
||||
$loggedInUser = $this->user(); // Try default web guard first
|
||||
|
||||
// If not on web guard, check other guards
|
||||
if (!$loggedInUser) {
|
||||
$guards = ['organization', 'bank', 'admin'];
|
||||
foreach ($guards as $guard) {
|
||||
$loggedInUser = auth()->guard($guard)->user();
|
||||
if ($loggedInUser) {
|
||||
Log::info("Found authenticated user on '{$guard}' guard", [
|
||||
'user_id' => $loggedInUser->id,
|
||||
'user_type' => get_class($loggedInUser),
|
||||
]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!$loggedInUser) {
|
||||
Log::warning("Authorization failed: No authenticated user on any guard.");
|
||||
return false;
|
||||
}
|
||||
|
||||
$isAssociated = false; // Flag to track if user is associated with the profile
|
||||
$emailToVerify = null;
|
||||
|
||||
// --- Check Association and Get Email ---
|
||||
|
||||
// First check: Is the logged-in entity the same as the profile being verified?
|
||||
if (get_class($loggedInUser) === get_class($profileModel) && $loggedInUser->id === $profileModel->id) {
|
||||
// User is verifying their own profile (e.g., Organization verifying Organization email)
|
||||
$isAssociated = true;
|
||||
$emailToVerify = method_exists($profileModel, 'getEmailForVerification')
|
||||
? $profileModel->getEmailForVerification()
|
||||
: $profileModel->email;
|
||||
Log::info("Authorization: Logged-in entity is verifying own email", [
|
||||
'entity_type' => get_class($profileModel),
|
||||
'entity_id' => $profileModel->id,
|
||||
]);
|
||||
} elseif ($profileModel instanceof \App\Models\User) {
|
||||
// Case 1: Profile is a User model (and logged-in user is different)
|
||||
if ($loggedInUser instanceof \App\Models\User && $profileModel->id === $loggedInUser->id) {
|
||||
$isAssociated = true;
|
||||
$emailToVerify = $loggedInUser->getEmailForVerification();
|
||||
} else {
|
||||
Log::warning("Authorization failed: User ID mismatch. Profile ID: {$profileModel->id}, Logged-in User ID: {$loggedInUser->id}");
|
||||
}
|
||||
} else {
|
||||
// Case 2: Profile is Organization, Bank, Admin, etc. and logged-in user is a User
|
||||
if ($loggedInUser instanceof \App\Models\User) {
|
||||
// Check 'users' relationship first
|
||||
if (method_exists($profileModel, 'users')) {
|
||||
if ($profileModel->users()->whereKey($loggedInUser->id)->exists()) {
|
||||
$isAssociated = true;
|
||||
}
|
||||
}
|
||||
// If not associated via 'users', check 'managers' relationship
|
||||
elseif (method_exists($profileModel, 'managers')) {
|
||||
if ($profileModel->managers()->whereKey($loggedInUser->id)->exists()) {
|
||||
$isAssociated = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ($isAssociated) {
|
||||
// Use the profileModel's email for verification
|
||||
$emailToVerify = method_exists($profileModel, 'getEmailForVerification')
|
||||
? $profileModel->getEmailForVerification()
|
||||
: $profileModel->email;
|
||||
} else {
|
||||
Log::warning("Authorization failed: User ID {$loggedInUser->id} not associated with " . class_basename($profileModel) . " ID {$profileModel->id} via users() or managers().");
|
||||
}
|
||||
} else {
|
||||
Log::warning("Authorization failed: Logged-in entity is not a User and doesn't match profile", [
|
||||
'logged_in_type' => get_class($loggedInUser),
|
||||
'logged_in_id' => $loggedInUser->id,
|
||||
'profile_type' => get_class($profileModel),
|
||||
'profile_id' => $profileModel->id,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
// If user is not associated, deny authorization
|
||||
if (!$isAssociated) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// --- Compare Hash ---
|
||||
if ($emailToVerify === null) {
|
||||
Log::error("Authorization failed: Could not determine email to verify for " . class_basename($profileModel) . " ID {$profileModel->id}");
|
||||
return false; // Should not happen if $isAssociated is true, but safety check
|
||||
}
|
||||
|
||||
$routeHash = (string) $this->route('hash');
|
||||
if (!hash_equals(sha1($emailToVerify), $routeHash)) {
|
||||
Log::error("Email hash mismatch for " . class_basename($profileModel) . " ID {$profileModel->id}. Email: {$emailToVerify}, Route Hash: {$routeHash}");
|
||||
return false;
|
||||
}
|
||||
|
||||
// --- Authorization Successful ---
|
||||
$this->profileModel = $profileModel;
|
||||
Log::info("Authorization successful for email verification of " . class_basename($profileModel) . " id: " . $profileModel->id . " by user id: " . $loggedInUser->id );
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
//
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Fulfill the email verification request.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function fulfill()
|
||||
{
|
||||
Log::info('ProfileEmailVerificationRequest::fulfill() called', [
|
||||
'profileModel_class' => $this->profileModel ? get_class($this->profileModel) : 'null',
|
||||
'profileModel_id' => $this->profileModel?->id,
|
||||
'hasVerifiedEmail' => $this->profileModel?->hasVerifiedEmail(),
|
||||
'email_verified_at_before' => $this->profileModel?->email_verified_at,
|
||||
]);
|
||||
|
||||
if (!$this->profileModel->hasVerifiedEmail()) {
|
||||
$result = $this->profileModel->markEmailAsVerified();
|
||||
|
||||
Log::info('ProfileEmailVerificationRequest::fulfill() markEmailAsVerified result', [
|
||||
'result' => $result,
|
||||
'email_verified_at_after' => $this->profileModel->fresh()->email_verified_at,
|
||||
]);
|
||||
|
||||
event(new ProfileVerified($this->profileModel));
|
||||
|
||||
Log::info('ProfileEmailVerificationRequest::fulfill() ProfileVerified event dispatched');
|
||||
} else {
|
||||
Log::info('ProfileEmailVerificationRequest::fulfill() email already verified, skipping');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure the validator instance.
|
||||
*
|
||||
* @param \Illuminate\Validation\Validator $validator
|
||||
* @return \Illuminate\Validation\Validator
|
||||
*/
|
||||
public function withValidator(Validator $validator)
|
||||
{
|
||||
return $validator;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user