Files
Verde-Web/app/Http/Controllers/Api/V1/Auth/LoginController.php
admin dc297d4cd7 feat(backend): complete Module 1 auth (register/login/OTP/reset)
Closes Module 1: 9 auth endpoints under /api/v1/auth, OTP via SMS
(Semaphore + log + fake drivers), role middleware, role + admin seeders,
27 feature tests passing.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-29 21:46:53 +08:00

51 lines
1.6 KiB
PHP

<?php
namespace App\Http\Controllers\Api\V1\Auth;
use App\Http\Controllers\Api\V1\ApiController;
use App\Http\Requests\Auth\LoginRequest;
use App\Http\Resources\UserResource;
use App\Models\User;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\Hash;
class LoginController extends ApiController
{
public function __invoke(LoginRequest $request): JsonResponse
{
$data = $request->validated();
$user = User::query()
->when($data['email'] ?? null, fn ($q, $email) => $q->where('email', $email))
->when($data['phone'] ?? null, fn ($q, $phone) => $q->where('phone', $phone))
->first();
if (! $user || ! Hash::check($data['password'], $user->password)) {
return $this->fail('Invalid credentials', null, 401);
}
if ($user->status === User::STATUS_SUSPENDED) {
return $this->forbidden('Account suspended');
}
if ($user->status === User::STATUS_PENDING) {
return $this->fail(
'Account pending verification. Verify the OTP sent during registration.',
['account' => ['Verify your phone before logging in.']],
403,
);
}
$user->forceFill(['last_login_at' => now()])->save();
$deviceName = $data['device_name'] ?? $request->userAgent() ?? 'unknown';
$token = $user->createToken($deviceName);
return $this->ok([
'user' => new UserResource($user),
'token' => $token->plainTextToken,
'token_type' => 'Bearer',
], 'Login successful');
}
}