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/Pin.php
<?php

namespace App\Http\Controllers\Authentication;

use App\Models\Gig;
use App\Models\Shop;
use App\Models\User;
use App\Models\UserPin;
use App\Models\SellerNin;
use App\Models\UserActivity;
use App\Services\OtpService;
use Illuminate\Http\Request;
use App\Services\ActivityLogger;
use Illuminate\Support\Facades\Log;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Http;

class Pin extends Controller
{
    // Set PIN for first timer
    public function setupPin(Request $request)
    {
        try {
            $validatedData = $request->validate([
                'user_id' => 'required|exists:users,id',
                'pin' => 'required|digits:4',
                'device_name' => 'required|string',
            ]);

            $hashedPin = Hash::make($validatedData['pin']);

            // Update or create the user PIN
            $userPin = UserPin::updateOrCreate(
                ['user_id' => $validatedData['user_id']],
                [
                    'pin' => $hashedPin,
                    'status' => 'active'
                ]
            );

            $user = User::find($validatedData['user_id']);
            $user->update([
                'is_pin' => 1,

            ]);

            // Log the activite
            $device = $validatedData['device_name'];
            $activityLogger = app(ActivityLogger::class);
            $activityLogger->log('User set PIN from mobile phone (API)', $user->id, $user->role, $device);

            return response()->json(['status' => 'success', 'message' => 'PIN set successfully'], 200);
        } catch (\Throwable $th) {
            Log::info($th->getMessage());
            return response()->json(['status' => 'error', 'message' => 'Unable to set PIN. ' . $th->getMessage()], 400);
        }
    }

    // Login PIN
    public function loginPin(Request $request)
    {
        try {

            $validatedData = $request->validate([
                'pin' => 'required|digits:4',
                'user_id' => 'required|exists:users,id',
                'device_name' => 'required',
                'ip_address' => 'required',
            ]);


            // Check if the user pin exists and is valid
            $userPin = UserPin::where('user_id', $validatedData['user_id'])->first();
            if (!$userPin || !Hash::check($validatedData['pin'], $userPin->pin)) {
                return response()->json(['status' => 'error', 'message' => 'Your PIN in incorrecct'], 401);
            }

            // Check if the user exists and is active
            $user = User::where('id', $validatedData['user_id'])->where('status', 'active')->first();
            if ($user) {
                // return $user;
                $ip = $validatedData['ip_address'];
                $location = $this->getLocation($ip);
                $activityIp = UserActivity::where('user_id', $user->id)->first();
                $location = ($activityIp && $activityIp === $ip) ? $activityIp : $this->getLocation($ip);
                //if user city or state is null make the call
                if ($user->city == null) {
                    $location = $this->getLocation($ip);
                }

                // Update user's location
                $user->latitude = $location['latitude'] ?? $user->latitude;
                $user->longitude = $location['longitude'] ??  $user->longitude;
                $user->save();

                // Check if the user has a shop
                $shop = Shop::where('user_id', $user->id)->exists();

                // Create a token
                $token = $user->createToken('api_token')->plainTextToken;
                
                // Log the activity
                $device = $validatedData['device_name'];
                $activityLogger = app(ActivityLogger::class);
                $activityLogger->log('User confirmed and logged in from mobile phone (API)', $user->id, $user->role, $device);

                // update device_token

                // $this->updateDeviceToken($user, $validatedData['device_token']);
                $isNin = SellerNin::where('user_id', $user->id)->exists();
            } else {
                return response()->json(['status' => 'error', 'message' => 'Your account is inactive'], 404);
            }

            // Return a successful response
            return response()->json([
                'status' => 'success',
                'message' => 'Welcome back',
                'token' => $token,
                'is_shop' => $shop ?? [],
                'user' => $user,
                'is_nin' => $isNin,
            ], 200);
        } catch (\Throwable $th) {
            Log::error($th->getMessage());
            return response()->json(['status' => 'error', 'message' => 'Unable to confirm PIN. ' . $th->getMessage()], 400);
        }
    }

    // Location
    private function getLocation($ip)
    {
        try {
            $clientIp = $ip;
            $apiKey = env('IP2LOCATION_API_KEY');
            $response = Http::get("https://api.ip2location.io/?key={$apiKey}&ip={$clientIp}&format=json");
            if ($response->successful()) {
                return $data = $response->json();
            }
        } catch (\Exception $e) {
            Log::error('Location fetching error: ' . $e->getMessage());
        }
    }

    // Forget PIN
    public function forgetPin(Request $request)
    {
        try {
            $validatedData = $request->validate([
                'user_id' => 'required|exists:users,id',
                'password' => 'required',
                'email' => 'required|email|exists:users,email',
                'device_name' => 'required',
            ]);

            $user = User::find($validatedData['user_id']);

            if ($user) {
                if (!Hash::check($validatedData['password'], $user->password)) {
                    return response()->json(['status' => 'error', 'message' => 'Invalid password'], 401);
                }

                // Email OTP Services
                $otpService = app(OtpService::class);
                $otpService->sendOtpToEmail($validatedData['email']);

                // Log the activity
                $device = $validatedData['device_name'];
                $activityLogger = app(ActivityLogger::class);
                $activityLogger->log('User requested PIN reset from mobile phone (API)', $user->id, $user->role, $device);

                return response()->json(['status' => 'success', 'message' => 'Email confirmation code sent successfully to your email.'], 200);
            } else {
                return response()->json(['status' => 'error', 'message' => 'User not found. Unable to send OTP'], 404);
            }
        } catch (\Throwable $th) {
            Log::info($th->getMessage());
            return response()->json(['status' => 'error', 'message' => 'Please try again later ' . $th->getMessage()], 400);
        }
    }

    // Change PIN
    public function setNewPin(Request $request)
    {
        try {
            // Validate the input data
            $validatedData = $request->validate([
                'user_id' => 'required|exists:users,id',
                'token' => 'required|numeric|exists:otp_verifications,otp|digits:6',
                'new_pin' => 'required|digits:4',
                'device_name' => 'required',
            ]);

            // Find the user and their PIN entry
            $user = User::find($validatedData['user_id']);
            $userPin = UserPin::where('user_id', $validatedData['user_id'])->first();

            // Check if the new PIN is the same as the current PIN
            if (Hash::check($validatedData['new_pin'], $userPin->pin)) {
                return response()->json(['status' => 'error', 'message' => 'You have used this PIN before. Please choose a different PIN.'], 400);
            }

            // Hash the new PIN and update the record
            $newHashedPin = Hash::make($validatedData['new_pin']);
            $userPin->update(['pin' => $newHashedPin]);

            // Log the activity
            $device = $validatedData['device_name'];
            $activityLogger = app(ActivityLogger::class);
            $activityLogger->log('User changed PIN from mobile phone (API)', $user->id, $user->role, $device);

            return response()->json(['status' => 'success', 'message' => 'PIN changed successfully'], 200);
        } catch (\Throwable $th) {
            Log::info($th->getMessage());
            return response()->json(['status' => 'error', 'message' => 'Unable to change PIN. ' . $th->getMessage()], 400);
        }
    }
}