This commit is contained in:
Devit
2026-03-29 19:45:29 +05:00
parent 2cd5ebb4fd
commit 7a20be6e1b
3 changed files with 314 additions and 91 deletions

View File

@@ -10,8 +10,6 @@ use App\Models\Blog;
use App\Models\Category;
use App\Models\Chat;
use App\Models\City;
use App\Models\Client;
use App\Models\Clientsreg;
use App\Models\ContactUs;
use App\Models\Country;
use App\Models\Currency;
@@ -172,7 +170,7 @@ class ApiController extends Controller
$countryCode = ltrim($request->country_code, '+');
// 1⃣ First: try with mobile + country code
$mobileWithCode = $countryCode . $mobile;
$mobileWithCode = $countryCode . $mobile;
// First try strict match
$user = User::where('type', 'phone')
@@ -180,28 +178,28 @@ class ApiController extends Controller
->withTrashed()
->first();
if (!$user) {
return ResponseService::errorResponse(
__('User not found. Please signup first.')
);
}
if (!$user) {
return ResponseService::errorResponse(
__('User not found. Please signup first.')
);
}
if ($user->deleted_at) {
return ResponseService::errorResponse(
__('User is deactivated. Please contact the administrator.')
);
}
if ($user->deleted_at) {
return ResponseService::errorResponse(
__('User is deactivated. Please contact the administrator.')
);
}
// password exists check
if (empty($user->password)) {
return ResponseService::errorResponse(
__('Password is not set. Please set your password using the forgot password option.')
);
}
// password exists check
if (empty($user->password)) {
return ResponseService::errorResponse(
__('Password is not set. Please set your password using the forgot password option.')
);
}
if (! Hash::check($request->password, $user->password)) {
return ResponseService::errorResponse(__('Invalid password.'));
}
if (! Hash::check($request->password, $user->password)) {
return ResponseService::errorResponse(__('Invalid password.'));
}
}
$socialLogin = null;
if (! empty($firebase_id)) {
@@ -708,7 +706,7 @@ class ApiController extends Controller
}
// Get all_category_ids from request (should contain category and all parent categories)
$allCategoryIds = $request->input('all_category_ids', []);
$allCategoryIds = $request->input('all_category_ids', []);
// If it comes as comma-separated string, convert to array
if (is_string($allCategoryIds)) {
@@ -982,9 +980,9 @@ class ApiController extends Controller
->where(function ($query) {
// Either no parent or parent status != 0
$query->whereDoesntHave('parent') // no parent category
->orWhereHas('parent', function ($q2) {
$q2->where('status', '!=', 0);
});
->orWhereHas('parent', function ($q2) {
$q2->where('status', '!=', 0);
});
});
})
->when($request->id, function ($sql) use ($request) {
@@ -1727,49 +1725,49 @@ class ApiController extends Controller
// dd($packageCategoryIds);
// Get the requested category
$requestedCategory = Category::find($request->category_id);
$requestedCategory = Category::find($request->category_id);
$requestedCategory = Category::find($request->category_id);
if ($requestedCategory) {
// Check if user has access to the category or any of its subcategories
if (! $hasGlobalPackage) {
$hasAccess = false;
if (! $hasGlobalPackage) {
$hasAccess = false;
// 1⃣ Direct category access
if (in_array($requestedCategory->id, $packageCategoryIds)) {
// 1⃣ Direct category access
if (in_array($requestedCategory->id, $packageCategoryIds)) {
$hasAccess = true;
}
// 2⃣ Check ancestors (parent → root)
if (! $hasAccess) {
$ancestorIds = $requestedCategory->ancestors()
->where('status', 1)
->pluck('id')
->toArray();
if (! empty(array_intersect($ancestorIds, $packageCategoryIds))) {
$hasAccess = true;
}
}
// 2️⃣ Check ancestors (parentroot)
if (! $hasAccess) {
$ancestorIds = $requestedCategory->ancestors()
->where('status', 1)
->pluck('id')
->toArray();
// 3️⃣ Check descendants (children → deep)
if (! $hasAccess) {
$descendantIds = $requestedCategory->descendants()
->where('status', 1)
->pluck('id')
->toArray();
if (! empty(array_intersect($ancestorIds, $packageCategoryIds))) {
$hasAccess = true;
}
}
// 3⃣ Check descendants (children → deep)
if (! $hasAccess) {
$descendantIds = $requestedCategory->descendants()
->where('status', 1)
->pluck('id')
->toArray();
if (! empty(array_intersect($descendantIds, $packageCategoryIds))) {
$hasAccess = true;
}
}
// ❌ No access
if (! $hasAccess) {
ResponseService::errorResponse(
__('You need to purchase a package for this category to access it.')
);
if (! empty(array_intersect($descendantIds, $packageCategoryIds))) {
$hasAccess = true;
}
}
// ❌ No access
if (! $hasAccess) {
ResponseService::errorResponse(
__('You need to purchase a package for this category to access it.')
);
}
}
// If hasGlobalPackage is true, user has access to all categories
} else {
ResponseService::errorResponse(__('Category not found.'));
@@ -3953,10 +3951,126 @@ class ApiController extends Controller
return ResponseService::errorResponse();
}
}
public function getOtp(Request $request)
{
try {
$validator = Validator::make($request->query(), [
'country_code' => 'required|string|max:5',
'number' => 'required|string|max:15',
]);
if ($validator->fails()) {
return ResponseService::validationError($validator->errors()->first());
}
// Normalize inputs
$countryCode = ltrim(trim($request->query('country_code')), '+');
$number = preg_replace('/\D/', '', $request->query('number'));
$toNumber = '+' . $countryCode . $number;
// ✅ Oddiy validation (Twilio orniga)
if (!preg_match('/^\+\d{10,15}$/', $toNumber)) {
return ResponseService::errorResponse(__('Invalid phone number.'));
}
$otp = rand(100000, 999999);
$expireAt = now()->addMinutes(10);
NumberOtp::updateOrCreate(
[
'number' => $number,
],
[
'otp' => $otp,
'expire_at' => $expireAt,
]
);
// ✅ Eskiz orqali yuborish
dispatch(new SendSmsJob($toNumber, $otp));
return ResponseService::successResponse(__('OTP sent successfully.'));
} catch (\Throwable $th) {
ResponseService::logErrorResponse($th, 'OTP Controller -> getOtp');
return ResponseService::errorResponse();
}
}
public function verifyOtp(Request $request)
{
try {
$validator = Validator::make($request->all(), [
'number' => 'required|string',
'country_code' => 'required|string',
'otp' => 'required|numeric|digits:6',
'password' => 'nullable|string|min:6',
]);
if ($validator->fails()) {
return ResponseService::validationError($validator->errors()->first());
}
$number = $request->query('number');
$countryCode = $request->query('country_code');
// Format full phone number
// $requestNumber = $countryCode.$number;
// $trimmedNumber = ltrim($requestNumber, '+');
// $toNumber = '+'.$trimmedNumber;
$otpRecord = NumberOtp::where('number', $number)->first();
if (! $otpRecord) {
return ResponseService::errorResponse(__('OTP not found.'));
}
if (now()->isAfter($otpRecord->expire_at)) {
return ResponseService::validationError(__('OTP has expired.'));
}
if ($otpRecord->attempts >= 3) {
$otpRecord->delete();
return ResponseService::validationError(__('OTP expired after 3 failed attempts.'));
}
if ($otpRecord->otp != $request->otp) {
$otpRecord->increment('attempts');
return ResponseService::validationError(__('Invalid OTP.'));
}
$otpRecord->delete();
$user = User::where('mobile', $request->number)->where('type', 'phone')->first();
if (! $user) {
$user = User::create([
'mobile' => $request->number,
'type' => 'phone',
'country_code' => $countryCode,
'password' => ! empty($request->password) ? Hash::make($request->password) : '',
]);
$user->assignRole('User');
}else{
if (! empty($countryCode)) {
$user->country_code = ltrim($countryCode, '+');
}
$user->save();
}
Auth::login($user);
$auth = User::find(Auth::id());
$token = $auth->createToken($auth->name ?? '')->plainTextToken;
return ResponseService::successResponse(__('User logged-in successfully'), $auth, ['token' => $token]);
} catch (Throwable $th) {
ResponseService::logErrorResponse($th, 'OTP Controller -> verifyOtp');
return ResponseService::errorResponse();
}
}
public function userExists(Request $request)
{
$validator = Validator::make($request->all(), [
@@ -3974,24 +4088,24 @@ class ApiController extends Controller
$countryCode = ltrim($request->country_code, '+');
$mobileWithCode = $countryCode . $mobile;
$userExists = User::where('type', 'phone')
->where('mobile', $mobile)
->withTrashed()
->first();
->where('mobile', $mobile)
->withTrashed()
->first();
if (! $userExists) {
return ResponseService::errorResponse(
__('User does not exist'),
['user_exists' => false]
);
}
if (! $userExists) {
return ResponseService::errorResponse(
__('User does not exist'),
['user_exists' => false]
);
}
// ❌ user found but deactivated
if ($userExists->deleted_at) {
return ResponseService::errorResponse(
__('User is deactivated. Please contact the administrator.'),
['user_exists' => false]
);
}
// ❌ user found but deactivated
if ($userExists->deleted_at) {
return ResponseService::errorResponse(
__('User is deactivated. Please contact the administrator.'),
['user_exists' => false]
);
}
if ($userExists) {
return ResponseService::successResponse(
__('User already exists'),