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\Exceptions\AppException;
6use App\Services\AuthService;
7use Illuminate\Http\JsonResponse;
8use Illuminate\Http\Request;
9use Illuminate\Support\Facades\Http;
10use Illuminate\Support\Facades\Log;
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     * Authenticate a user and return an API token.
37     *
38     * @param  Request  $request  Expected keys: 'email' (string), 'password' (string)
39     * @return JsonResponse
40     *
41     * @response {
42     *   "token": "string",
43     *   "token_expires_at": "datetime",
44     *   "token_type": "Bearer"
45     * }
46     */
47    public function login(Request $request)
48    {
49        try {
50            if (empty($request->all())) {
51                throw new \Exception('Request parameters not set', 404);
52            }
53
54            $request->validate([
55                'email' => 'required|string|email',
56                'password' => 'required|string',
57            ]);
58
59            $token = null;
60
61            if ($request->header('X-Auth-Token') && $request->header('X-Request-Source') == 'external_app') {
62                $token = $this->authService->validateCrossAppToken($request->header('X-Auth-Token'));
63            }
64
65            $tokenData = $this->authService->login(
66                $request->input('email'),
67                $request->input('password'),
68                $token
69            );
70
71            if (! $token) {
72                $crossAppToken = $this->authService->generateCrossAppToken($tokenData['api_token']);
73
74                $response = Http::withHeaders([
75                    'X-Auth-Token' => $crossAppToken,
76                    'X-Request-Source' => 'external_app',
77                ])->asForm()->post('https://crm.fireservicetitan.com:8081/api/login', [
78                    'email' => $request->input('email'),
79                    'password' => $request->input('password'),
80                ]);
81
82                /*if (!in_array($response->status(), $this->statusException, true)) {
83                    throw new \Exception('Connection Auth failed', 502);
84                }*/
85                Log::channel('third-party')->warning('Not token generated in crm for '.$request->input('email'));
86            }
87
88            return response()->json([
89                'token' => $tokenData['api_token'],
90                'token_expires_at' => $tokenData['token_expires_at'],
91                'token_type' => 'Bearer',
92            ]);
93
94        } catch (\Exception $e) {
95            report(AppException::fromException($e, 'AUTH_EXCEPTION'));
96            $code = $e->getCode() ?: 500;
97
98            Log::channel('third-party')->error("Auth error: {$e->getMessage()}", [
99                'code' => $code,
100                'email' => $request->input('email'),
101            ]);
102
103            return response()->json(
104                ['error' => $this->statusError[$code]],
105                $code
106            );
107        }
108    }
109}