GOOD SHELL MAS BOY
Server: Apache/2.4.52 (Ubuntu)
System: Linux vmi1836763.contaboserver.net 5.15.0-130-generic #140-Ubuntu SMP Wed Dec 18 17:59:53 UTC 2024 x86_64
User: www-data (33)
PHP: 8.4.10
Disabled: NONE
Upload Files
File: /var/www/console.fixgini.com/app/Http/Controllers/Authentication/Register.php
<?php

namespace App\Http\Controllers\Authentication;

use App\Models\User;
use App\Mail\AccountDeleteOtpMail;

use App\Mail\OtpMail;
use App\Models\Country;
use App\Models\Wallet;
use App\Mail\WelcomeMail;
use Illuminate\Http\Request;
use App\Models\OtpVerification;
use App\Services\ActivityLogger;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Http;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Mail;
use Illuminate\Validation\ValidationException;

class Register extends Controller
{


    public function register(Request $request)
    {
        DB::beginTransaction();
        try {
           
            if (User::where('email', $request->email)->exists()) {
            return response()->json([
                'status' => 'error',
                'message' => 'Email already exists.'
            ], 409); // Conflict status code
        }

        if (User::where('phone', $request->phone)->exists()) {
            return response()->json([
                'status' => 'error',
                'message' => 'Phone already exists.'
            ], 409);
        }

            $validatedData = $request->validate([
                'name' => 'required|string|max:255',
                'email' => 'required|email|unique:users,email',
                'phone' => 'nullable|numeric|unique:users,phone',
                'role' => 'required|string|max:255',
                'device_name' => 'required|string|max:255',
                'password' => 'required|valid_password',
                'ip_address' => 'required',
                'nationality_id' => 'required|exists:countries,id',
            ], [
                'nationality_id.required' => 'The nationality field is required.',
                'nationality_id.exists' => 'The selected nationality is invalid.',
            ]);


            info($validatedData);
            
            $ip = $validatedData['ip_address'];

            $location = $this->ipInfo($ip);

            $user = User::create([
                'name' => ucwords(strtolower($validatedData['name'])),
                'email' => $validatedData['email'],
                'phone' => $validatedData['phone'] ?? '',
                'city' => $location['city'] ?? '',
                'state' => $location['state'] ?? '',
                'latitude' => $location['latitude'] ?? '',
                'longitude' => $location['longitude'] ?? '',
                'nationality_id' => $validatedData['nationality_id'],
                'role' => $validatedData['role'],
                'is_fingerprint' => false,
                'is_pin' => false,
                'profile_photo_url' => 'https://console.fixgini.com/icon.png',
                'password' => Hash::make($validatedData['password']),
            ]);

            $currency = Country::where('id', $validatedData['nationality_id'])->first();
            Wallet::create([
                'user_id' => $user->id,
                'currency' => $currency->symbol
            ]);

            $device = $validatedData['device_name'];

            // Log the user activity
            $activityLogger = app(ActivityLogger::class);
            $activityLogger->log('New account registration', $user->id, $user->role, $device);

            // Send welcome email
            Mail::to($validatedData['email'])->send(new WelcomeMail($user));

            // Send confirmation email code
            if($validatedData['role'] == 'buyer'){
                info('email verification code sent to buyer');
                $this->sendEmailOtp($user);
            }
            // Generate authentication token
            $token = $user->createToken('api_token')->plainTextToken;

            DB::commit();

            return response()->json(['status' => 'success', 'user' => $user, 'message' => 'Registration successful.', 'token' => $token], 200);
        } catch (\Exception $e) {
            DB::rollBack();
            Log::error('Unable to register: ' . $e->getMessage());
            return response()->json(['status' => 'error', 'message' => $e->getMessage()], 500);
        }
    }

    private function getLocation($ip)
    {
        try {
            $clientIp = $ip;

            // Attempt the first API call to api.ip2location.io
            $apiKey = env('IP2LOCATION_API_KEY');
            $response = Http::get("https://api.ip2location.io/?key={$apiKey}&ip={$clientIp}&format=json");
            info($response->json());
            if ($response->successful()) {
                $data = $response->json();
                $latitude = $data['latitude'] ?? '';
                $longitude = $data['longitude'] ?? '';
                $city = $data['city_name'] ?? '';
                $state = $data['region_name'] ?? '';

                // If lat/lng exists, perform reverse geocoding
                // if ($latitude && $longitude) {
                //     return $this->reverseGeocode($latitude, $longitude);
                // }
            } else {
                // Check for specific error in the first API response
                $error = $response->json('error') ?? [];
                if (isset($error['error_code']) && $error['error_code'] === 10000) {
                    Log::warning('IP2Location API error: ' . $error['error_message']);
                }
            }

            // Fallback to ipinfo.io API
          
        } catch (\Exception $e) {
            Log::error('Location fetching error: ' . $e->getMessage());
        }

        // Return a default response if all attempts fail
        return [
            'city' => '',
            'state' => '',
            'country' => '',
            'latitude' => '',
            'longitude' => '',
        ];
    } 

   private function ipInfo($clientIp)
   {
        $response = Http::get("https://ipinfo.io/{$clientIp}?token=dff86f66bbd177");
        if ($response->successful()) {
            $data = $response->json();
            // Extract location data from ipinfo response
            $location = explode(',', $data['loc'] ?? '');
            $latitude = $location[0] ?? '';
            $longitude = $location[1] ?? '';

            // Include city and state in the response
            return [
                'city' => $data['city'] ?? '',
                'state' => $data['region'] ?? '',
                'country' => $data['country'] ?? '',
                'latitude' => $latitude ?? '',
                'longitude' => $longitude ?? '',
            ];
        } else{
                $this->getLocation($clientIp);
        }
   }

    private function reverseGeocode($latitude, $longitude)
    {
        try {
            $response = Http::get('https://maps.googleapis.com/maps/api/geocode/json', [
                'latlng' => "{$latitude},{$longitude}",
                'key' => env('GOOGLE_API_KEY'),
            ]);

            if ($response->successful()) {
                $data = $response->json();
                info($data);

                if (isset($data['results']) && count($data['results']) > 0) {
                    $components = $data['results'][0]['address_components'];
                    $locationInfo = [
                        'city' => null,
                        'state' => null,
                        'latitude' => $latitude,
                        'longitude' => $longitude,
                    ];

                    foreach ($components as $component) {
                        if (in_array('locality', $component['types'])) {
                            $locationInfo['city'] = $component['long_name'];
                        }
                        if (in_array('administrative_area_level_1', $component['types'])) {
                            $locationInfo['state'] = $component['long_name'];
                        }
                    }
                    return $locationInfo;
                } else {
                    return [
                        'error' => true,
                        'message' => 'No results found.',
                    ];
                }
            } else {
                return [
                    'error' => true,
                    'message' => 'Failed to retrieve location data.',
                ];
            }
        } catch (\Exception $e) {
            return [
                'error' => true,
                'message' => $e->getMessage(),
            ];
        }
    }

    private function sendEmailOtp($user)
    {
        try {
            $user = User::where('email', $user['email'])->first();

            if ($user->email_verified_at) {
                return response()->json(['status' => 'failed', 'message' => 'Email already verified'], 401);
            }

            // Email OTP Services
            $otp = random_int(100000, 999999);
            Mail::to($user->email)->send(new OtpMail($otp));
            OtpVerification::updateOrCreate(
                ['email' => $user->email],
                ['otp' => $otp]
            );
            return response()->json(['status' => 'success', 'message' => 'Email confirmation code sent successfully'], 200);
        } catch (\Throwable $th) {
            Log::error($th->getMessage());
            return response()->json(['status' => 'failed', 'message' => 'Network Issue! Pls try again later'], 400);
        }
    }



  
     public function sendMailOtp2(Request $request)
    {
        try {
           // $user = User::where('email', $user['email'])->first();

            // $user = User::where('email', $request->email)->first();

            $request->validate([
            'email' => 'required|email',
            

        ]);
    /*
            if ($user->email_verified_at) {
                return response()->json(['status' => 'failed', 'message' => 'Email already verified'], 401);
            } */

            // Email OTP Services
            $otp = random_int(100000, 999999);
            Mail::to($request->email)->send(new AccountDeleteOtpMail($otp));
            OtpVerification::updateOrCreate(
                ['email' => $request->email],
                ['otp' => $otp]
            );
            return response()->json(['status' => 'success', 'message' => 'Account deletion OTP sent successfully'], 200);
        } catch (\Throwable $th) {
            Log::error($th->getMessage());
            return response()->json(['status' => 'failed', 'message' => 'Network Issue! Pls try again later'], 400);
        }
    }
    



    public function verifyEmailOtp(Request $request)
    {
        try {
            $validatedData = $request->validate([
                'email' => 'required|email|exists:users,email',
                'otp' => 'required|digits:6|exists:otp_verifications,otp',
            ]);

            $otpRecord = OtpVerification::where([
                ['email', '=', $validatedData['email']],
                ['otp', '=', $validatedData['otp']],
                ['status', '=', 'unverified']
            ])->latest()->first();

            if (!$otpRecord) {
                return response()->json(['message' => 'Invalid OTP. Pls try again', 'status' => 'error'], 401);
            }

            $otpRecord->update(['status' => 'verified']);

            $user = User::where('email', $validatedData['email'])->first();
            if ($user) {
                $user->update(['email_verified_at' => now(), 'status' => 'active']);
            }
            $otpRecord->delete();
            return response()->json(['message' => 'Email verified successfully', 'status' => 'success'], 200);
        } catch (ValidationException $e) {
            Log::error($e->getMessage());
            return response()->json(['status' => 'error', 'message' => 'Please retry, Something happened'], 422);
        }
    }


    // verify delete account  otp



     public function verifyDeleteOtp(Request $request)
    {
        try {
            $validatedData = $request->validate([
                'email' => 'required|email|exists:users,email',
                'otp' => 'required|digits:6|exists:otp_verifications,otp',
            ]);

            $otpRecord = OtpVerification::where([
                ['email', '=', $validatedData['email']],
                ['otp', '=', $validatedData['otp']],
                ['delete_status', '=', 'unverified']
            ])->latest()->first();

            if (!$otpRecord) {
                return response()->json(['message' => 'Invalid OTP. Pls try again', 'status' => 'error'], 401);
            }

          
           
             $otpRecord->update(['delete_status' => 'verified']);
            return response()->json(['message' => 'Otp verified successfully', 'status' => 'success'], 200);
        } catch (ValidationException $e) {
            Log::error($e->getMessage());
            return response()->json(['status' => 'error', 'message' => 'Please retry, Something happened'], 422);
        }
    }



    //verify delete account otp

    public function requestAccountDeletion(Request $request)
{
    try {
        $validatedData = $request->validate([
            'email' => 'required|email|exists:users,email',
        ]);

        $user = User::where('email', $validatedData['email'])->first();
        if (!$user) {
            return response()->json(['status' => 'error', 'message' => 'User not found'], 404);
        }

        // Generate OTP
        $otp = random_int(100000, 999999);
        Mail::to($user->email)->send(new OtpMail($otp));
        
        OtpVerification::updateOrCreate(
            ['email' => $user->email],
            ['otp' => $otp, 'status' => 'unverified']
        );

        return response()->json(['status' => 'success', 'message' => 'OTP sent for account deletion'], 200);
    } catch (\Throwable $th) {
        Log::error('Error sending OTP for account deletion: ' . $th->getMessage());
        return response()->json(['status' => 'error', 'message' => 'Network issue! Please try again later'], 500);
    }
}

public function confirmAccountDeletion(Request $request)
{
    try {
        $validatedData = $request->validate([
            'email' => 'required|email|exists:users,email',
            'otp' => 'required|digits:6|exists:otp_verifications,otp',
        ]);

        $otpRecord = OtpVerification::where([
            ['email', '=', $validatedData['email']],
            ['otp', '=', $validatedData['otp']],
            ['delete_status', '=', 'unverified']
        ])->latest()->first();

        if (!$otpRecord) {
            return response()->json(['status' => 'error', 'message' => 'Invalid OTP. Please try again'], 401);
        }

        $user = User::where('email', $validatedData['email'])->first();
        if (!$user) {
            return response()->json(['status' => 'error', 'message' => 'User not found'], 404);
        }

        DB::beginTransaction();
        $otpRecord->delete();
        $user->delete();
        DB::commit();

        return response()->json(['status' => 'success', 'message' => 'Account deleted successfully'], 200);
    } catch (ValidationException $e) {
        return response()->json(['status' => 'error', 'message' => $e->getMessage()], 422);
    } catch (\Exception $e) {
        DB::rollBack();
        Log::error('Account deletion error: ' . $e->getMessage());
        return response()->json(['status' => 'error', 'message' => 'Something went wrong. Please try again.'], 500);
    }
}

}