178 lines
5.1 KiB
PHP
Executable File
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,
|
|
]);
|
|
}
|
|
}
|
|
}
|
|
}
|