Files
getgreen-backend/app/Http/Controllers/API/AuthController.php

178 lines
5.1 KiB
PHP
Executable File

<?php
namespace App\Http\Controllers\API;
use App\Http\Controllers\Controller;
use App\Models\Cart;
use App\Models\User;
use App\Services\API\SmsService;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Cookie;
use Illuminate\Support\Facades\RateLimiter;
use Symfony\Component\HttpFoundation\Response;
class AuthController extends Controller
{
public function resend(Request $request)
{
$request->validate([
'phone' => 'required',
]);
$phone = preg_replace("/[^0-9]/", "", $request->phone);
// Define the same rate limit key to share attempts between auth and resend
$rateLimitKey = 'verify_attempts_' . $phone;
// Set the same maximum attempts and decay time
$maxAttempts = 5;
$decayMinutes = 1;
// Check if the phone number has exceeded the rate limit
if (RateLimiter::tooManyAttempts($rateLimitKey, $maxAttempts)) {
$seconds = RateLimiter::availableIn($rateLimitKey);
return response()->json([
'message' => 'Too many attempts. Please try again in ' . $seconds . ' seconds.'
], 429); // 429 Too Many Requests
}
$user = User::where('phone', $phone)->first();
if ($user) {
// send SMS with verify code
$verify_code = SmsService::send($phone);
$user->update([
'verify_code' => $verify_code,
]);
// Increase the attempt count
RateLimiter::hit($rateLimitKey, $decayMinutes * 60);
return response()->json(['phone' => $phone]);
}
// return can't find user message
return response()->json(['message' => 'User not found']);
}
public function auth(Request $request)
{
$phone = preg_replace("/[^0-9]/", "", $request->input('phone'));
// Define the rate limit key based on the phone number.
$rateLimitKey = 'verify_attempts_' . $phone;
// Set the maximum attempts and the decay time (e.g., 5 attempts every 1 minute)
$maxAttempts = 5;
$decayMinutes = 1;
// Check if the phone number has exceeded the rate limit
if (RateLimiter::tooManyAttempts($rateLimitKey, $maxAttempts)) {
$seconds = RateLimiter::availableIn($rateLimitKey);
return response()->json([
'message' => 'Too many attempts. Please try again in ' . $seconds . ' seconds.'
], 429); // 429 Too Many Requests
}
$user = User::where('phone', $phone)->first();
// send SMS with verify code
$verify_code = SmsService::send($phone);
if ($user) {
$user->update([
'verify_code' => $verify_code,
]);
} else {
User::create([
'phone' => $phone,
'verify_code' => $verify_code,
]);
}
// Increase the attempt count
RateLimiter::hit($rateLimitKey, $decayMinutes * 60);
return response()->json(['phone' => $phone]);
}
public function verify(Request $request)
{
$request->validate([
'phone' => 'required',
'verify_code' => 'required',
]);
$phone = preg_replace("/[^0-9]/", "", $request->phone);
$user = User::where('phone', $phone)->first();
// check if user exists
if (!$user) {
return response()->json([
'message' => 'User not found'
], Response::HTTP_NOT_FOUND);
}
// check if verify code is correct
if ($user->verify_code != $request->verify_code) {
return response([
'message' => 'Verify code is incorrect'
], Response::HTTP_UNAUTHORIZED);
}
$token = $user->createToken('token')->plainTextToken;
$cookie = cookie('jwt', $token, 60 * 24 * 365, null, null, secure: true, httpOnly: true); // 1 year expiration
// clear verify code
$user->update([
'verify_code' => null,
]);
// Update cart, remove token and add user_id
$this->updateCart($user);
return response([
'data' => [
'id' => $user->id,
'phone' => $user->phone,
'access_token' => $token
]
])->withCookie($cookie);
}
public function logout()
{
$cookie = Cookie::forget('jwt');
// logout
auth()->user()->tokens()->delete();
return response([
'message' => 'Success'
])->withCookie($cookie);
}
private function getLocalToken()
{
return request()->header('X-Application-Token');
}
private function updateCart($user)
{
if ($this->getLocalToken()) {
// Update carts, remove token and add user_id
$carts = Cart::where('token', $this->getLocalToken())->get();
foreach ($carts as $cart) {
$cart->update([
'token' => null,
'user_id' => $user->id,
]);
}
}
}
}