initial: bootstrap from BukidBountyApp base
This commit is contained in:
60
.claude/plans/98b3202e344f4ad777c9555b5e93fe70-complete.md
Normal file
60
.claude/plans/98b3202e344f4ad777c9555b5e93fe70-complete.md
Normal file
@@ -0,0 +1,60 @@
|
||||
---
|
||||
task: Fix LoginController null dereference causing 500 on login with non-existent user
|
||||
cycles: 3
|
||||
context: true
|
||||
private: false
|
||||
started: 2026-05-16T15:59:00Z
|
||||
finished: 2026-05-16T15:59:30Z
|
||||
---
|
||||
|
||||
## files
|
||||
- app/Http/Controllers/LoginController.php [lines 34-49] — bug site: Log::info reads $user->active and $user->acct_type->value BEFORE the null guard on line 44
|
||||
|
||||
## steps
|
||||
1. In `LoginController::authenticate` move the `Log::info('Login attempt', [...])` block (lines 36-42) to AFTER the `if (!$user)` early return on line 44. The log then only fires for users that actually exist, eliminating the null dereference.
|
||||
- Alternatively: keep the log in place but use null-safe operators — `$user?->active` and `$user?->acct_type?->value` — so PHP 8 does not throw when `$user` is null.
|
||||
- Preferred: move the log after the null check (cleaner, no PHP-version nuance).
|
||||
|
||||
## context
|
||||
```php
|
||||
// LoginController.php — current broken order (lines 34-49):
|
||||
$user = User::whereIn('mobile_number', $candidates)->first();
|
||||
|
||||
Log::info('Login attempt', [ // <-- fires BEFORE null check
|
||||
'mobile_number' => $credentials['mobile_number'],
|
||||
'candidates' => $candidates,
|
||||
'user_found' => !!$user,
|
||||
'active' => $user->active ?? null, // ERROR in PHP 8 when $user === null
|
||||
'acct_type' => $user->acct_type->value ?? null, // ERROR in PHP 8 when $user === null
|
||||
]);
|
||||
|
||||
if (!$user) { // <-- null check is TOO LATE
|
||||
return Response::json(['success' => false, 'message' => 'Account not found.'], 401);
|
||||
}
|
||||
```
|
||||
|
||||
Fix — move log after null guard:
|
||||
```php
|
||||
$user = User::whereIn('mobile_number', $candidates)->first();
|
||||
|
||||
if (!$user) {
|
||||
return Response::json(['success' => false, 'message' => 'Account not found.'], 401);
|
||||
}
|
||||
|
||||
Log::info('Login attempt', [
|
||||
'mobile_number' => $credentials['mobile_number'],
|
||||
'candidates' => $candidates,
|
||||
'user_found' => true,
|
||||
'active' => $user->active,
|
||||
'acct_type' => $user->acct_type->value ?? null,
|
||||
]);
|
||||
```
|
||||
|
||||
Root cause: PHP 8.0+ changed property access on null from a Warning to a fatal Error. The `??` null-coalescing operator does NOT catch Errors — only null/undefined values. So `$user->active ?? null` still throws `Error: Attempt to read property "active" on null` when `$user` is null.
|
||||
|
||||
Symptom: `POST /post/loginnow` returns HTTP 500 (generic Server Error page) for any mobile number that has no matching user record, instead of returning 401 `{"success":false,"message":"Account not found."}`.
|
||||
|
||||
## notes
|
||||
- dictionary: ai-docs/dictionary.md
|
||||
- linters: none
|
||||
- constraints: Hypervel (PHP 8.2). Do NOT use Illuminate classes. Use `Response::json()` facade, not `response()->json()`.
|
||||
Reference in New Issue
Block a user