764 lines
29 KiB
PHP
764 lines
29 KiB
PHP
<?php
|
|
|
|
namespace App\Http\Controllers\Api;
|
|
|
|
use App\Http\Controllers\Controller;
|
|
use App\Models\User;
|
|
use App\Models\EmployerProfile;
|
|
use App\Models\Sponsor;
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Support\Facades\Hash;
|
|
use Illuminate\Support\Facades\Validator;
|
|
use Illuminate\Support\Str;
|
|
|
|
class EmployerAuthController extends Controller
|
|
{
|
|
/**
|
|
* Authenticate an employer and return a secure Bearer token.
|
|
*
|
|
* @param \Illuminate\Http\Request $request
|
|
* @return \Illuminate\Http\JsonResponse
|
|
*/
|
|
public function login(Request $request)
|
|
{
|
|
$validator = Validator::make($request->all(), [
|
|
'email' => 'nullable|string',
|
|
'mobile' => 'nullable|string',
|
|
'password' => 'required|string',
|
|
'fcm_token' => 'nullable|string|max:255',
|
|
]);
|
|
|
|
$validator->after(function ($validator) use ($request) {
|
|
if (!$request->filled('email') && !$request->filled('mobile')) {
|
|
$validator->errors()->add('mobile', 'Either mobile number or email is required.');
|
|
}
|
|
});
|
|
|
|
if ($validator->fails()) {
|
|
return response()->json([
|
|
'success' => false,
|
|
'message' => 'Validation error.',
|
|
'errors' => $validator->errors()
|
|
], 422);
|
|
}
|
|
|
|
try {
|
|
$loginValue = $request->input('mobile') ?? $request->input('email');
|
|
|
|
$sponsor = Sponsor::where('mobile', $loginValue)
|
|
->orWhere('email', $loginValue)
|
|
->first();
|
|
|
|
if ($sponsor) {
|
|
$user = User::where('email', $sponsor->email)
|
|
->where('role', 'employer')
|
|
->first();
|
|
} else {
|
|
$user = User::where('email', $loginValue)
|
|
->where('role', 'employer')
|
|
->first();
|
|
}
|
|
|
|
if (!$sponsor && !$user) {
|
|
return response()->json([
|
|
'success' => false,
|
|
'message' => 'Invalid credentials.'
|
|
], 401);
|
|
}
|
|
|
|
$passwordHash = $sponsor ? $sponsor->password : $user->password;
|
|
|
|
if (!Hash::check($request->password, $passwordHash)) {
|
|
return response()->json([
|
|
'success' => false,
|
|
'message' => 'Invalid credentials.'
|
|
], 401);
|
|
}
|
|
|
|
if ($sponsor && $sponsor->status === 'suspended') {
|
|
return response()->json([
|
|
'success' => false,
|
|
'message' => 'Your account has been suspended. Please contact support.'
|
|
], 403);
|
|
}
|
|
|
|
$apiToken = Str::random(80);
|
|
|
|
if ($user) {
|
|
// Employer account
|
|
$profile = EmployerProfile::where('user_id', $user->id)->first();
|
|
$verification_status = $profile ? $profile->verification_status : 'approved';
|
|
|
|
if ($verification_status === 'pending') {
|
|
return response()->json([
|
|
'success' => false,
|
|
'message' => 'Your account is pending verification.'
|
|
], 403);
|
|
}
|
|
|
|
if ($verification_status === 'rejected') {
|
|
return response()->json([
|
|
'success' => false,
|
|
'message' => 'Your account verification has been rejected.',
|
|
'reason' => $profile->rejection_reason ?? 'Verification rejected.'
|
|
], 403);
|
|
}
|
|
|
|
$userUpdateData = ['api_token' => $apiToken];
|
|
if ($request->has('fcm_token')) {
|
|
$userUpdateData['fcm_token'] = $request->fcm_token;
|
|
}
|
|
$user->update($userUpdateData);
|
|
if ($sponsor) {
|
|
$sponsorUpdateData = [
|
|
'api_token' => $apiToken,
|
|
'last_login_at' => now(),
|
|
];
|
|
if ($request->has('fcm_token')) {
|
|
$sponsorUpdateData['fcm_token'] = $request->fcm_token;
|
|
}
|
|
$sponsor->update($sponsorUpdateData);
|
|
}
|
|
|
|
if ($request->filled('fcm_token')) {
|
|
\App\Services\FCMService::sendPushNotification(
|
|
$request->fcm_token,
|
|
'Successful Login',
|
|
'Welcome back to your Migrant employer account.'
|
|
);
|
|
}
|
|
|
|
return response()->json([
|
|
'success' => true,
|
|
'message' => 'Login successful.',
|
|
'role' => 'employer',
|
|
'data' => [
|
|
'employer' => $user->load('employerProfile'),
|
|
'token' => $apiToken
|
|
]
|
|
], 200);
|
|
} else {
|
|
// Pure Sponsor account
|
|
$sponsorUpdateData = [
|
|
'api_token' => $apiToken,
|
|
'last_login_at' => now(),
|
|
];
|
|
if ($request->has('fcm_token')) {
|
|
$sponsorUpdateData['fcm_token'] = $request->fcm_token;
|
|
}
|
|
$sponsor->update($sponsorUpdateData);
|
|
|
|
if ($request->filled('fcm_token')) {
|
|
\App\Services\FCMService::sendPushNotification(
|
|
$request->fcm_token,
|
|
'Successful Login',
|
|
'Welcome back to your Migrant sponsor account.'
|
|
);
|
|
}
|
|
|
|
return response()->json([
|
|
'success' => true,
|
|
'message' => 'Login successful.',
|
|
'role' => 'sponsor',
|
|
'data' => [
|
|
'sponsor' => $sponsor->makeHidden(['password', 'api_token']),
|
|
'token' => $apiToken
|
|
]
|
|
], 200);
|
|
}
|
|
|
|
} catch (\Exception $e) {
|
|
logger()->error('Mobile Login Failure: ' . $e->getMessage());
|
|
|
|
return response()->json([
|
|
'success' => false,
|
|
'message' => 'An error occurred during login. Please try again.',
|
|
'error' => app()->environment('local') ? $e->getMessage() : 'Internal Server Error'
|
|
], 500);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Register a new employer via API.
|
|
*
|
|
* @param \Illuminate\Http\Request $request
|
|
* @return \Illuminate\Http\JsonResponse
|
|
*/
|
|
public function register(Request $request)
|
|
{
|
|
$validator = Validator::make($request->all(), [
|
|
'name' => 'required|string|max:255',
|
|
'email' => 'required|string|email|max:255|unique:users,email|unique:sponsors,email',
|
|
'phone' => 'required|string|max:50|unique:employer_profiles,phone|unique:sponsors,mobile',
|
|
'fcm_token' => 'nullable|string|max:255',
|
|
'emirates_id' => 'nullable|array',
|
|
'address' => 'nullable|string|max:255',
|
|
], [
|
|
'email.unique' => 'This email address is already registered.',
|
|
'phone.unique' => 'This mobile number is already registered.',
|
|
]);
|
|
|
|
if ($validator->fails()) {
|
|
return response()->json([
|
|
'success' => false,
|
|
'message' => 'Validation error.',
|
|
'errors' => $validator->errors()
|
|
], 422);
|
|
}
|
|
|
|
try {
|
|
$otp = '111111'; // default development OTP
|
|
if (app()->environment('production')) {
|
|
$otp = strval(rand(100000, 999999));
|
|
}
|
|
|
|
\Illuminate\Support\Facades\Cache::put('employer_otp_' . $request->email, [
|
|
'code' => $otp,
|
|
'expires_at' => now()->addMinutes(10)->timestamp
|
|
], 600);
|
|
|
|
$emiratesIdInput = $request->input('emirates_id');
|
|
$emiratesIdNumber = null;
|
|
$emiratesIdExpiry = null;
|
|
$emiratesIdName = null;
|
|
$emiratesIdDob = null;
|
|
$emiratesIdNationality = null;
|
|
$emiratesIdIssueDate = null;
|
|
$emiratesIdEmployer = null;
|
|
$emiratesIdIssuePlace = null;
|
|
$emiratesIdOccupation = null;
|
|
|
|
if (is_array($emiratesIdInput)) {
|
|
$emiratesIdNumber = $emiratesIdInput['emirates_id_number'] ?? $emiratesIdInput['id_number'] ?? $emiratesIdInput['id number'] ?? $emiratesIdInput['card_number'] ?? null;
|
|
$emiratesIdExpiry = $emiratesIdInput['expiry_date'] ?? $emiratesIdInput['expiry date'] ?? $emiratesIdInput['emirates_id_expiry'] ?? null;
|
|
$emiratesIdName = $emiratesIdInput['name'] ?? null;
|
|
$emiratesIdDob = $emiratesIdInput['date_of_birth'] ?? $emiratesIdInput['date of birth'] ?? $emiratesIdInput['dob'] ?? null;
|
|
$emiratesIdNationality = $emiratesIdInput['nationality'] ?? null;
|
|
$emiratesIdIssueDate = $emiratesIdInput['issue_date'] ?? $emiratesIdInput['issue date'] ?? null;
|
|
$emiratesIdEmployer = $emiratesIdInput['employer'] ?? null;
|
|
$emiratesIdIssuePlace = $emiratesIdInput['issue_place'] ?? $emiratesIdInput['issue place'] ?? null;
|
|
$emiratesIdOccupation = $emiratesIdInput['occupation'] ?? $emiratesIdInput['occuption'] ?? null;
|
|
}
|
|
|
|
// Create inactive User
|
|
$user = User::create([
|
|
'name' => $request->name,
|
|
'email' => $request->email,
|
|
'password' => Hash::make(Str::random(16)), // temporary password
|
|
'role' => 'employer',
|
|
'subscription_status' => 'none',
|
|
'subscription_expires_at' => null,
|
|
'fcm_token' => $request->fcm_token,
|
|
]);
|
|
|
|
// Create pending Profile
|
|
EmployerProfile::create([
|
|
'user_id' => $user->id,
|
|
'company_name' => $request->name . ' Household',
|
|
'phone' => $request->phone,
|
|
'country' => 'United Arab Emirates',
|
|
'verification_status' => 'pending',
|
|
'language' => 'English',
|
|
'notifications' => true,
|
|
'emirates_id_number' => $emiratesIdNumber,
|
|
'emirates_id_expiry' => $emiratesIdExpiry,
|
|
'emirates_id_name' => $emiratesIdName,
|
|
'emirates_id_dob' => $emiratesIdDob,
|
|
'nationality' => $emiratesIdNationality,
|
|
'emirates_id_issue_date' => $emiratesIdIssueDate,
|
|
'emirates_id_employer' => $emiratesIdEmployer,
|
|
'emirates_id_issue_place' => $emiratesIdIssuePlace,
|
|
'emirates_id_occupation' => $emiratesIdOccupation,
|
|
'address' => $request->address,
|
|
]);
|
|
|
|
// Create unverified Sponsor
|
|
\App\Models\Sponsor::create([
|
|
'full_name' => $request->name,
|
|
'email' => $request->email,
|
|
'mobile' => $request->phone,
|
|
'password' => $user->password,
|
|
'country_code' => 'AE',
|
|
'subscription_status' => 'none',
|
|
'subscription_plan' => null,
|
|
'subscription_start_date' => null,
|
|
'subscription_end_date' => null,
|
|
'payment_status' => 'unpaid',
|
|
'is_verified' => false,
|
|
'otp_verified_at' => null,
|
|
'status' => 'inactive',
|
|
'fcm_token' => $request->fcm_token,
|
|
'emirates_id' => $emiratesIdNumber,
|
|
'address' => $request->address,
|
|
]);
|
|
|
|
if ($request->filled('fcm_token')) {
|
|
\App\Services\FCMService::sendPushNotification(
|
|
$request->fcm_token,
|
|
'Registration Initiated',
|
|
'Your verification code has been sent to your email.'
|
|
);
|
|
}
|
|
|
|
// Try sending email
|
|
try {
|
|
\Illuminate\Support\Facades\Mail::to($request->email)->send(new \App\Mail\EmployerOtpMail(
|
|
$otp,
|
|
$request->name . ' Household',
|
|
$request->name
|
|
));
|
|
} catch (\Exception $mailEx) {
|
|
logger()->error('API Sponsor Registration Mail Failure: ' . $mailEx->getMessage());
|
|
}
|
|
|
|
return response()->json([
|
|
'success' => true,
|
|
'message' => 'Verification code sent to email successfully.',
|
|
'email' => $request->email
|
|
], 201);
|
|
|
|
} catch (\Exception $e) {
|
|
logger()->error('API Sponsor Registration Failure: ' . $e->getMessage());
|
|
return response()->json([
|
|
'success' => false,
|
|
'message' => 'Registration failed. Please try again.',
|
|
'error' => app()->environment('local') ? $e->getMessage() : 'Internal Server Error'
|
|
], 500);
|
|
}
|
|
}
|
|
|
|
public function verify(Request $request)
|
|
{
|
|
$validator = Validator::make($request->all(), [
|
|
'email' => 'required|email',
|
|
'otp' => 'required|string|size:6',
|
|
'fcm_token' => 'nullable|string|max:255',
|
|
]);
|
|
|
|
if ($validator->fails()) {
|
|
return response()->json([
|
|
'success' => false,
|
|
'errors' => $validator->errors()
|
|
], 422);
|
|
}
|
|
$cachedData = \Illuminate\Support\Facades\Cache::get('employer_otp_' . $request->email);
|
|
|
|
if (!$cachedData || !isset($cachedData['code']) || !isset($cachedData['expires_at'])) {
|
|
return response()->json([
|
|
'success' => false,
|
|
'message' => 'Invalid or expired verification code.'
|
|
], 400);
|
|
}
|
|
|
|
// Handle any dirty/legacy cache objects gracefully
|
|
if (is_object($cachedData['expires_at']) || $cachedData['expires_at'] instanceof \__PHP_Incomplete_Class) {
|
|
\Illuminate\Support\Facades\Cache::forget('employer_otp_' . $request->email);
|
|
return response()->json([
|
|
'success' => false,
|
|
'message' => 'Session expired. Please request a new verification code.'
|
|
], 400);
|
|
}
|
|
|
|
if ($cachedData['code'] !== $request->otp || now()->timestamp > $cachedData['expires_at']) {
|
|
return response()->json([
|
|
'success' => false,
|
|
'message' => 'Invalid or expired verification code.'
|
|
], 400);
|
|
}
|
|
|
|
try {
|
|
// Update Sponsor verification status
|
|
$sponsor = \App\Models\Sponsor::where('email', $request->email)->first();
|
|
$user = User::where('email', $request->email)->where('role', 'employer')->first();
|
|
$fcmToken = $request->fcm_token;
|
|
|
|
if ($sponsor) {
|
|
$sponsorUpdateData = [
|
|
'is_verified' => true,
|
|
'otp_verified_at' => now(),
|
|
];
|
|
if ($fcmToken) {
|
|
$sponsorUpdateData['fcm_token'] = $fcmToken;
|
|
}
|
|
$sponsor->update($sponsorUpdateData);
|
|
}
|
|
|
|
if ($user && $fcmToken) {
|
|
$user->update(['fcm_token' => $fcmToken]);
|
|
}
|
|
|
|
$tokenToSend = $fcmToken ?? ($sponsor ? $sponsor->fcm_token : null) ?? ($user ? $user->fcm_token : null);
|
|
if ($tokenToSend) {
|
|
\App\Services\FCMService::sendPushNotification(
|
|
$tokenToSend,
|
|
'Email Verified',
|
|
'Proceed to payment selection.'
|
|
);
|
|
}
|
|
|
|
// Clear Cache
|
|
\Illuminate\Support\Facades\Cache::forget('employer_otp_' . $request->email);
|
|
|
|
return response()->json([
|
|
'success' => true,
|
|
'message' => 'Email verified successfully. Proceed to payment selection.',
|
|
'email' => $request->email
|
|
]);
|
|
} catch (\Exception $e) {
|
|
return response()->json([
|
|
'success' => false,
|
|
'message' => 'Verification failed. Please try again.'
|
|
], 500);
|
|
}
|
|
}
|
|
|
|
// Upload Emirates ID during registration steps (Unauthenticated).
|
|
|
|
|
|
public function payment(Request $request)
|
|
{
|
|
$validator = Validator::make($request->all(), [
|
|
'email' => 'required|email',
|
|
'plan_id' => 'required|string',
|
|
'amount_aed' => 'required|numeric',
|
|
'paytabs_transaction_id' => 'required|string',
|
|
]);
|
|
|
|
if ($validator->fails()) {
|
|
return response()->json([
|
|
'success' => false,
|
|
'errors' => $validator->errors()
|
|
], 422);
|
|
}
|
|
|
|
try {
|
|
$user = User::where('email', $request->email)->first();
|
|
$sponsor = \App\Models\Sponsor::where('email', $request->email)->first();
|
|
|
|
if (!$user || !$sponsor) {
|
|
return response()->json([
|
|
'success' => false,
|
|
'message' => 'User account not found.'
|
|
], 404);
|
|
}
|
|
|
|
if (!$sponsor->is_verified) {
|
|
return response()->json([
|
|
'success' => false,
|
|
'message' => 'Please verify your email before initiating payment.'
|
|
], 403);
|
|
}
|
|
|
|
\Illuminate\Support\Facades\DB::transaction(function () use ($request, $user, $sponsor) {
|
|
// Update User subscription
|
|
$user->update([
|
|
'subscription_status' => 'active',
|
|
'subscription_expires_at' => now()->addDays(30),
|
|
]);
|
|
|
|
// Update Sponsor status
|
|
$sponsor->update([
|
|
'subscription_status' => 'active',
|
|
'subscription_plan' => $request->plan_id,
|
|
'subscription_start_date' => now(),
|
|
'subscription_end_date' => now()->addDays(30),
|
|
'payment_status' => 'paid',
|
|
]);
|
|
|
|
// Insert into subscriptions table
|
|
\Illuminate\Support\Facades\DB::table('subscriptions')->insert([
|
|
'user_id' => $user->id,
|
|
'plan_id' => $request->plan_id,
|
|
'amount_aed' => $request->amount_aed,
|
|
'starts_at' => now(),
|
|
'expires_at' => now()->addDays(30),
|
|
'paytabs_transaction_id' => $request->paytabs_transaction_id,
|
|
'status' => 'active',
|
|
'created_at' => now(),
|
|
'updated_at' => now(),
|
|
]);
|
|
});
|
|
|
|
return response()->json([
|
|
'success' => true,
|
|
'message' => 'Subscription payment processed and activated successfully.',
|
|
'email' => $request->email
|
|
]);
|
|
} catch (\Exception $e) {
|
|
return response()->json([
|
|
'success' => false,
|
|
'message' => 'Payment processing failed. Please try again.'
|
|
], 500);
|
|
}
|
|
}
|
|
|
|
public function password(Request $request)
|
|
{
|
|
$validator = Validator::make($request->all(), [
|
|
'email' => 'required|email',
|
|
'password' => 'required|string|min:8|confirmed',
|
|
'fcm_token' => 'nullable|string|max:255',
|
|
]);
|
|
|
|
if ($validator->fails()) {
|
|
return response()->json([
|
|
'success' => false,
|
|
'errors' => $validator->errors()
|
|
], 422);
|
|
}
|
|
|
|
try {
|
|
$user = User::where('email', $request->email)->first();
|
|
$sponsor = \App\Models\Sponsor::where('email', $request->email)->first();
|
|
|
|
if (!$user || !$sponsor) {
|
|
return response()->json([
|
|
'success' => false,
|
|
'message' => 'User account not found.'
|
|
], 404);
|
|
}
|
|
|
|
if ($sponsor->payment_status !== 'paid') {
|
|
return response()->json([
|
|
'success' => false,
|
|
'message' => 'Please complete subscription payment first.'
|
|
], 403);
|
|
}
|
|
|
|
// Generate API Bearer token
|
|
$apiToken = Str::random(80);
|
|
|
|
\Illuminate\Support\Facades\DB::transaction(function () use ($request, $user, $sponsor, $apiToken) {
|
|
$hashedPassword = Hash::make($request->password);
|
|
$fcmToken = $request->fcm_token;
|
|
|
|
$userUpdateData = [
|
|
'password' => $hashedPassword,
|
|
'api_token' => $apiToken,
|
|
];
|
|
if ($fcmToken) {
|
|
$userUpdateData['fcm_token'] = $fcmToken;
|
|
}
|
|
$user->update($userUpdateData);
|
|
|
|
$sponsorUpdateData = [
|
|
'password' => $hashedPassword,
|
|
'status' => 'active',
|
|
];
|
|
if ($fcmToken) {
|
|
$sponsorUpdateData['fcm_token'] = $fcmToken;
|
|
}
|
|
$sponsor->update($sponsorUpdateData);
|
|
|
|
// Approve profile verification
|
|
$profile = EmployerProfile::where('user_id', $user->id)->first();
|
|
if ($profile) {
|
|
$profile->update([
|
|
'verification_status' => 'approved'
|
|
]);
|
|
}
|
|
});
|
|
|
|
$tokenToSend = $request->fcm_token ?? ($user ? $user->fcm_token : null) ?? ($sponsor ? $sponsor->fcm_token : null);
|
|
if ($tokenToSend) {
|
|
\App\Services\FCMService::sendPushNotification(
|
|
$tokenToSend,
|
|
'Welcome to Migrant',
|
|
'Your employer registration has been completed successfully.'
|
|
);
|
|
}
|
|
|
|
return response()->json([
|
|
'success' => true,
|
|
'message' => 'Password created successfully. Registration finalized.',
|
|
'data' => [
|
|
'sponsor' => $user->load('employerProfile'),
|
|
'token' => $apiToken
|
|
]
|
|
]);
|
|
|
|
} catch (\Exception $e) {
|
|
return response()->json([
|
|
'success' => false,
|
|
'message' => 'Failed to set password. Please try again.'
|
|
], 500);
|
|
}
|
|
}
|
|
|
|
public function plans()
|
|
{
|
|
return response()->json([
|
|
'success' => true,
|
|
'data' => [
|
|
'plans' => [
|
|
[
|
|
'id' => 'basic',
|
|
'name' => 'Basic Search',
|
|
'price' => 99.00,
|
|
'currency' => 'AED',
|
|
'period' => 'month',
|
|
'features' => ['Browse 500+ verified workers', 'Shortlist up to 10 candidates', 'Standard OCR verification'],
|
|
'popular' => false,
|
|
],
|
|
[
|
|
'id' => 'premium',
|
|
'name' => 'Premium Employer Pass',
|
|
'price' => 199.00,
|
|
'currency' => 'AED',
|
|
'period' => 'month',
|
|
'features' => ['Unlimited shortlisting', 'Direct candidate messaging', 'Priority interview scheduling', 'Dedicated support'],
|
|
'popular' => true,
|
|
],
|
|
[
|
|
'id' => 'enterprise',
|
|
'name' => 'VIP Concierge',
|
|
'price' => 499.00,
|
|
'currency' => 'AED',
|
|
'period' => 'month',
|
|
'features' => ['All Premium features', 'Assigned recruitment manager', 'Background medical verification guarantee', 'Free replacement within 30 days'],
|
|
'popular' => false,
|
|
]
|
|
]
|
|
]
|
|
]);
|
|
}
|
|
|
|
public function forgotPassword(Request $request)
|
|
{
|
|
$validator = Validator::make($request->all(), [
|
|
'email' => 'required|email',
|
|
]);
|
|
|
|
if ($validator->fails()) {
|
|
return response()->json([
|
|
'success' => false,
|
|
'message' => 'Validation error.',
|
|
'errors' => $validator->errors()
|
|
], 422);
|
|
}
|
|
|
|
try {
|
|
$user = User::where('email', $request->email)->where('role', 'employer')->first();
|
|
if (!$user) {
|
|
return response()->json([
|
|
'success' => false,
|
|
'message' => 'No employer account found with this email address.'
|
|
], 404);
|
|
}
|
|
|
|
$otp = '111111'; // default development OTP
|
|
if (app()->environment('production')) {
|
|
$otp = strval(rand(100000, 999999));
|
|
}
|
|
|
|
\Illuminate\Support\Facades\Cache::put('employer_reset_otp_' . $request->email, [
|
|
'code' => $otp,
|
|
'expires_at' => now()->addMinutes(10)->timestamp
|
|
], 600);
|
|
|
|
// Send reset OTP email
|
|
try {
|
|
\Illuminate\Support\Facades\Mail::to($request->email)->send(new \App\Mail\EmployerResetOtpMail(
|
|
$otp,
|
|
$user->name
|
|
));
|
|
} catch (\Exception $mailEx) {
|
|
logger()->error('API Employer Forgot Password Mail Failure: ' . $mailEx->getMessage());
|
|
}
|
|
|
|
return response()->json([
|
|
'success' => true,
|
|
'message' => 'Password reset verification code sent to email successfully.',
|
|
'email' => $request->email
|
|
], 200);
|
|
|
|
} catch (\Exception $e) {
|
|
logger()->error('API Employer Forgot Password Failure: ' . $e->getMessage());
|
|
return response()->json([
|
|
'success' => false,
|
|
'message' => 'An error occurred. Please try again.',
|
|
'error' => app()->environment('local') ? $e->getMessage() : 'Internal Server Error'
|
|
], 500);
|
|
}
|
|
}
|
|
|
|
public function resetPassword(Request $request)
|
|
{
|
|
$validator = Validator::make($request->all(), [
|
|
'email' => 'required|email',
|
|
'otp' => 'required|string|size:6',
|
|
'password' => 'required|string|min:8|confirmed',
|
|
]);
|
|
|
|
if ($validator->fails()) {
|
|
return response()->json([
|
|
'success' => false,
|
|
'message' => 'Validation error.',
|
|
'errors' => $validator->errors()
|
|
], 422);
|
|
}
|
|
|
|
$cachedData = \Illuminate\Support\Facades\Cache::get('employer_reset_otp_' . $request->email);
|
|
|
|
if (!$cachedData || !isset($cachedData['code']) || !isset($cachedData['expires_at'])) {
|
|
return response()->json([
|
|
'success' => false,
|
|
'message' => 'Invalid or expired verification code.'
|
|
], 400);
|
|
}
|
|
|
|
if ($cachedData['code'] !== $request->otp || now()->timestamp > $cachedData['expires_at']) {
|
|
return response()->json([
|
|
'success' => false,
|
|
'message' => 'Invalid or expired verification code.'
|
|
], 400);
|
|
}
|
|
|
|
try {
|
|
$user = User::where('email', $request->email)->where('role', 'employer')->first();
|
|
$sponsor = \App\Models\Sponsor::where('email', $request->email)->first();
|
|
|
|
if (!$user || !$sponsor) {
|
|
return response()->json([
|
|
'success' => false,
|
|
'message' => 'User account not found.'
|
|
], 404);
|
|
}
|
|
|
|
$apiToken = Str::random(80);
|
|
|
|
\Illuminate\Support\Facades\DB::transaction(function () use ($request, $user, $sponsor, $apiToken) {
|
|
$hashedPassword = Hash::make($request->password);
|
|
|
|
$user->update([
|
|
'password' => $hashedPassword,
|
|
'api_token' => $apiToken,
|
|
]);
|
|
|
|
$sponsor->update([
|
|
'password' => $hashedPassword,
|
|
]);
|
|
});
|
|
|
|
\Illuminate\Support\Facades\Cache::forget('employer_reset_otp_' . $request->email);
|
|
|
|
return response()->json([
|
|
'success' => true,
|
|
'message' => 'Password reset successfully.',
|
|
'data' => [
|
|
'employer' => $user->load('employerProfile'),
|
|
'token' => $apiToken
|
|
]
|
|
], 200);
|
|
|
|
} catch (\Exception $e) {
|
|
logger()->error('API Employer Reset Password Failure: ' . $e->getMessage());
|
|
return response()->json([
|
|
'success' => false,
|
|
'message' => 'Failed to reset password. Please try again.',
|
|
'error' => app()->environment('local') ? $e->getMessage() : 'Internal Server Error'
|
|
], 500);
|
|
}
|
|
}
|
|
}
|