Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
95.12% covered (success)
95.12%
39 / 41
50.00% covered (danger)
50.00%
1 / 2
CRAP
0.00% covered (danger)
0.00%
0 / 1
Auth
95.12% covered (success)
95.12%
39 / 41
50.00% covered (danger)
50.00%
1 / 2
8
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 login
95.00% covered (success)
95.00%
38 / 40
0.00% covered (danger)
0.00%
0 / 1
7
1<?php
2
3namespace App\Http\Controllers;
4
5use App\Services\AuthService;
6use Illuminate\Http\JsonResponse;
7use Illuminate\Http\Request;
8use Illuminate\Support\Facades\Http;
9use Illuminate\Support\Facades\Log;
10use App\Exceptions\AppException;
11
12class Auth extends Controller
13{
14    /**
15     * HTTP status codes and their corresponding error messages.
16     *
17     * @var array<int, string>
18     */
19    private array $statusError = [
20        404 => "Page not found",
21        401 => "Unauthorized",
22        500 => "Internal Server Error",
23        502 => "Bad Gateway",
24    ];
25
26    private $statusException = [
27        200,
28        201,
29        401,
30        404
31    ];
32
33    public function __construct(private readonly AuthService $authService)
34    {
35    }
36
37    /**
38     * Authenticate a user and return an API token.
39     *
40     * @param  Request  $request  Expected keys: 'email' (string), 'password' (string)
41     * @return JsonResponse
42     *
43     * @response {
44     *   "token": "string",
45     *   "token_expires_at": "datetime",
46     *   "token_type": "Bearer"
47     * }
48     */
49    public function login(Request $request)
50    {
51        try {
52            if (empty($request->all())) {
53                throw new \Exception('Request parameters not set', 404);
54            }
55
56            $request->validate([
57                'email' => 'required|string|email',
58                'password' => 'required|string',
59            ]);
60
61            $token = null;
62
63            if ($request->header('X-Auth-Token') && $request->header('X-Request-Source') == 'external_app') {
64                $token = $this->authService->validateCrossAppToken($request->header('X-Auth-Token'));
65            }
66
67            $tokenData = $this->authService->login(
68                $request->input('email'),
69                $request->input('password'),
70                $token
71            );
72
73            if (! $token) {
74                $crossAppToken = $this->authService->generateCrossAppToken($tokenData['api_token']);
75
76                $response = Http::withHeaders([
77                    'X-Auth-Token' => $crossAppToken,
78                    'X-Request-Source' => 'external_app',
79                ])->asForm()->post('https://crm.fireservicetitan.com:8081/api/login', [
80                    'email' => $request->input('email'),
81                    'password' => $request->input('password'),
82                ]);
83
84                /*if (!in_array($response->status(), $this->statusException, true)) {
85                    throw new \Exception('Connection Auth failed', 502);
86                }*/
87                Log::channel('third-party')->warning('Not token generated in crm for '.$request->input('email'));
88            }
89
90            return response()->json([
91                'token' => $tokenData['api_token'],
92                'token_expires_at' => $tokenData['token_expires_at'],
93                'token_type' => 'Bearer',
94            ]);
95
96        } catch (\Exception $e) {
97            report(AppException::fromException($e, 'AUTH_EXCEPTION'));
98            $code = $e->getCode() ?: 500;
99
100            Log::channel('third-party')->error("Auth error: {$e->getMessage()}", [
101                'code' => $code,
102                'email' => $request->input('email'),
103            ]);
104
105            return response()->json(
106                ['error' => $this->statusError[$code]],
107                $code
108            );
109        }
110    }
111}