feat(scanner): add scanner authentication and context services with routes and tests
This commit is contained in:
42
app/Domains/Auth/Controllers/ScannerLoginController.php
Normal file
42
app/Domains/Auth/Controllers/ScannerLoginController.php
Normal file
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
namespace App\Domains\Auth\Controllers;
|
||||
|
||||
use App\Domains\Auth\Requests\ScannerLoginRequest;
|
||||
use App\Domains\Auth\Resources\UserResource;
|
||||
use App\Domains\Auth\Services\PasswordLoginService;
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
|
||||
class ScannerLoginController extends Controller
|
||||
{
|
||||
public function __construct(
|
||||
private readonly PasswordLoginService $passwordLoginService,
|
||||
) {}
|
||||
|
||||
public function __invoke(ScannerLoginRequest $request): JsonResponse
|
||||
{
|
||||
$credentials = $request->validated();
|
||||
$user = $this->passwordLoginService->authenticateScanner(
|
||||
$credentials['email'],
|
||||
$credentials['password'],
|
||||
$request->ip(),
|
||||
$request->userAgent(),
|
||||
);
|
||||
|
||||
$expirationMinutes = (int) config('sanctum.expiration');
|
||||
$token = $user->createToken(
|
||||
'scanner-token',
|
||||
['scanner'],
|
||||
now()->addMinutes($expirationMinutes),
|
||||
)->plainTextToken;
|
||||
|
||||
return response()->json([
|
||||
'code' => 'auth.login_success',
|
||||
'message' => __('api.auth.login_success'),
|
||||
'token' => $token,
|
||||
'token_type' => 'Bearer',
|
||||
'user' => UserResource::make($user),
|
||||
]);
|
||||
}
|
||||
}
|
||||
24
app/Domains/Auth/Controllers/ScannerMeController.php
Normal file
24
app/Domains/Auth/Controllers/ScannerMeController.php
Normal file
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
namespace App\Domains\Auth\Controllers;
|
||||
|
||||
use App\Domains\Auth\Models\User;
|
||||
use App\Domains\Auth\Resources\ScannerMeResource;
|
||||
use App\Domains\Auth\Services\ScannerContextService;
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class ScannerMeController extends Controller
|
||||
{
|
||||
public function __construct(
|
||||
private readonly ScannerContextService $scannerContextService,
|
||||
) {}
|
||||
|
||||
public function __invoke(Request $request): ScannerMeResource
|
||||
{
|
||||
/** @var User $user */
|
||||
$user = $request->user();
|
||||
|
||||
return ScannerMeResource::make($this->scannerContextService->load($user));
|
||||
}
|
||||
}
|
||||
5
app/Domains/Auth/Requests/ScannerLoginRequest.php
Normal file
5
app/Domains/Auth/Requests/ScannerLoginRequest.php
Normal file
@@ -0,0 +1,5 @@
|
||||
<?php
|
||||
|
||||
namespace App\Domains\Auth\Requests;
|
||||
|
||||
class ScannerLoginRequest extends AdminAppLoginRequest {}
|
||||
21
app/Domains/Auth/Resources/ScannerMeResource.php
Normal file
21
app/Domains/Auth/Resources/ScannerMeResource.php
Normal file
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
namespace App\Domains\Auth\Resources;
|
||||
|
||||
use App\Domains\Auth\Models\User;
|
||||
use App\Domains\Tenant\Resources\TenantResource;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Resources\Json\JsonResource;
|
||||
|
||||
/** @mixin User */
|
||||
class ScannerMeResource extends JsonResource
|
||||
{
|
||||
/** @return array<string, mixed> */
|
||||
public function toArray(Request $request): array
|
||||
{
|
||||
return [
|
||||
'user' => UserResource::make($this->resource),
|
||||
'tenant' => TenantResource::make($this->tenant),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -62,6 +62,29 @@ class PasswordLoginService
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Authenticate a tenant-bound scanner without requiring its tenant code.
|
||||
*
|
||||
* @throws AccountLockedException
|
||||
* @throws ValidationException
|
||||
*/
|
||||
public function authenticateScanner(
|
||||
string $email,
|
||||
string $password,
|
||||
?string $ipAddress,
|
||||
?string $userAgent,
|
||||
): User {
|
||||
return $this->authenticateUser(
|
||||
$email,
|
||||
$password,
|
||||
null,
|
||||
$ipAddress,
|
||||
$userAgent,
|
||||
RoleCode::Scanner,
|
||||
true,
|
||||
);
|
||||
}
|
||||
|
||||
private function authenticateUser(
|
||||
string $email,
|
||||
string $password,
|
||||
@@ -210,7 +233,7 @@ class PasswordLoginService
|
||||
} catch (\Throwable $e) {
|
||||
Log::error('Failed to trigger reset password on account lock', [
|
||||
'user_id' => $user->id,
|
||||
'exception' => $e
|
||||
'exception' => $e,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
25
app/Domains/Auth/Services/ScannerContextService.php
Normal file
25
app/Domains/Auth/Services/ScannerContextService.php
Normal file
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
namespace App\Domains\Auth\Services;
|
||||
|
||||
use App\Domains\Auth\Models\User;
|
||||
use App\Domains\Authorization\Enums\RoleCode;
|
||||
|
||||
class ScannerContextService
|
||||
{
|
||||
public function load(User $user): User
|
||||
{
|
||||
$tenant = $user->tenant()
|
||||
->with([
|
||||
'menues' => fn ($query) => $query->whereHas(
|
||||
'roles',
|
||||
fn ($query) => $query->where('codigo', RoleCode::Scanner->value)
|
||||
),
|
||||
])
|
||||
->firstOrFail();
|
||||
|
||||
$user->setRelation('tenant', $tenant);
|
||||
|
||||
return $user;
|
||||
}
|
||||
}
|
||||
@@ -25,3 +25,4 @@ Route::middleware('auth:sanctum')->get('/me', MeController::class);
|
||||
Route::middleware('auth:sanctum')->put('/me', UpdateProfileController::class);
|
||||
|
||||
require __DIR__.'/adminapp.php';
|
||||
require __DIR__.'/scanner.php';
|
||||
|
||||
11
app/Domains/Auth/routes/scanner.php
Normal file
11
app/Domains/Auth/routes/scanner.php
Normal file
@@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
use App\Domains\Auth\Controllers\ScannerLoginController;
|
||||
use App\Domains\Auth\Controllers\ScannerMeController;
|
||||
use Illuminate\Support\Facades\Route;
|
||||
|
||||
Route::prefix('v1/scanner')->group(function (): void {
|
||||
Route::post('login', ScannerLoginController::class)->middleware('throttle:login');
|
||||
Route::middleware(['auth:sanctum', 'scanner.tenant'])
|
||||
->get('me', ScannerMeController::class);
|
||||
});
|
||||
Reference in New Issue
Block a user