feat(scanner): implement scanner bootstrap functionality with controller, request, resource, and service; add routes and migration for scanner domain
This commit is contained in:
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
namespace App\Domains\Bootstrap\Controllers;
|
||||
|
||||
use App\Domains\Bootstrap\Requests\ScannerBootstrapRequest;
|
||||
use App\Domains\Bootstrap\Resources\ScannerBootstrapResource;
|
||||
use App\Domains\Bootstrap\Services\ScannerBootstrapService;
|
||||
use App\Http\Controllers\Controller;
|
||||
|
||||
class ScannerBootstrapController extends Controller
|
||||
{
|
||||
public function __construct(protected ScannerBootstrapService $bootstrapService) {}
|
||||
|
||||
public function __invoke(ScannerBootstrapRequest $request): ScannerBootstrapResource
|
||||
{
|
||||
return ScannerBootstrapResource::make(
|
||||
$this->bootstrapService->get((string) $request->validated('dominio'))
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
<?php
|
||||
|
||||
namespace App\Domains\Bootstrap\Requests;
|
||||
|
||||
class ScannerBootstrapRequest extends TenantBootstrapRequest {}
|
||||
@@ -0,0 +1,5 @@
|
||||
<?php
|
||||
|
||||
namespace App\Domains\Bootstrap\Resources;
|
||||
|
||||
class ScannerBootstrapResource extends AdminAppBootstrapResource {}
|
||||
19
app/Domains/Bootstrap/Services/ScannerBootstrapService.php
Normal file
19
app/Domains/Bootstrap/Services/ScannerBootstrapService.php
Normal file
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
namespace App\Domains\Bootstrap\Services;
|
||||
|
||||
use App\Domains\Tenant\Models\WebsiteType;
|
||||
|
||||
class ScannerBootstrapService
|
||||
{
|
||||
/** @return array{website_type: WebsiteType} */
|
||||
public function get(string $domain): array
|
||||
{
|
||||
return [
|
||||
'website_type' => WebsiteType::query()
|
||||
->with(['siteLogo', 'footerLogo'])
|
||||
->where('scanner_domain', $domain)
|
||||
->firstOrFail(),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -7,3 +7,4 @@ Route::get('tenants/bootstrap/{dominio}', TenantBootstrapController::class)
|
||||
->where('dominio', '.*');
|
||||
|
||||
require __DIR__.'/adminapp.php';
|
||||
require __DIR__.'/scanner.php';
|
||||
|
||||
9
app/Domains/Bootstrap/routes/scanner.php
Normal file
9
app/Domains/Bootstrap/routes/scanner.php
Normal file
@@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
use App\Domains\Bootstrap\Controllers\ScannerBootstrapController;
|
||||
use Illuminate\Support\Facades\Route;
|
||||
|
||||
Route::get(
|
||||
'v1/scanner/bootstrap/{dominio}',
|
||||
ScannerBootstrapController::class
|
||||
);
|
||||
@@ -13,6 +13,7 @@ use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
'codigo',
|
||||
'nombre',
|
||||
'dominio',
|
||||
'scanner_domain',
|
||||
'primary_color',
|
||||
'secondary_color',
|
||||
'danger_color',
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
Schema::table('website_type', function (Blueprint $table): void {
|
||||
$table->string('scanner_domain')->nullable()->unique()->after('dominio');
|
||||
});
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('website_type', function (Blueprint $table): void {
|
||||
$table->dropUnique(['scanner_domain']);
|
||||
$table->dropColumn('scanner_domain');
|
||||
});
|
||||
}
|
||||
};
|
||||
@@ -31,6 +31,7 @@ class WebsiteTypeSeeder extends Seeder
|
||||
[
|
||||
'nombre' => 'ShopIt',
|
||||
'dominio' => 'localhost',
|
||||
'scanner_domain' => 'scanner.localhost',
|
||||
...self::PRESENTATION,
|
||||
'site_logo' => $this->onTicketLogo(),
|
||||
'footer_logo' => $this->onTicketFooterLogo(),
|
||||
@@ -63,6 +64,7 @@ class WebsiteTypeSeeder extends Seeder
|
||||
[
|
||||
'nombre' => 'OnTicket',
|
||||
'dominio' => 'onticket.localhost',
|
||||
'scanner_domain' => 'scanner.onticket.localhost',
|
||||
...self::PRESENTATION,
|
||||
'site_logo' => $this->onTicketLogo(),
|
||||
'footer_logo' => $this->onTicketFooterLogo(),
|
||||
|
||||
@@ -43,6 +43,7 @@ class WebsiteTypeSeederTest extends TestCase
|
||||
|
||||
$this->assertSame('ShopIt', $shopIt->nombre);
|
||||
$this->assertSame('localhost', $shopIt->dominio);
|
||||
$this->assertSame('scanner.localhost', $shopIt->scanner_domain);
|
||||
$this->assertSame($expectedPresentation, $shopIt->only(array_keys($expectedPresentation)));
|
||||
$this->assertSame('onticket_logo.png', $shopIt->siteLogo->filename);
|
||||
Storage::disk('s3')->assertExists($shopIt->siteLogo->path);
|
||||
@@ -70,6 +71,7 @@ class WebsiteTypeSeederTest extends TestCase
|
||||
|
||||
$this->assertSame('OnTicket', $onTicket->nombre);
|
||||
$this->assertSame('onticket.localhost', $onTicket->dominio);
|
||||
$this->assertSame('scanner.onticket.localhost', $onTicket->scanner_domain);
|
||||
$this->assertSame($expectedPresentation, $onTicket->only(array_keys($expectedPresentation)));
|
||||
$this->assertSame('onticket_logo.png', $onTicket->siteLogo->filename);
|
||||
Storage::disk('s3')->assertExists($onTicket->siteLogo->path);
|
||||
|
||||
76
tests/Feature/Tenant/BootstrapScannerControllerTest.php
Normal file
76
tests/Feature/Tenant/BootstrapScannerControllerTest.php
Normal file
@@ -0,0 +1,76 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Feature\Tenant;
|
||||
|
||||
use App\Domains\Attachable\Models\Attachment;
|
||||
use App\Domains\Tenant\Models\WebsiteType;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Tests\TestCase;
|
||||
|
||||
class BootstrapScannerControllerTest extends TestCase
|
||||
{
|
||||
use RefreshDatabase;
|
||||
|
||||
public function test_it_publicly_bootstraps_the_scanner_by_scanner_domain(): void
|
||||
{
|
||||
$siteLogo = Attachment::factory()->create();
|
||||
|
||||
WebsiteType::query()->create([
|
||||
'codigo' => 'shopit',
|
||||
'nombre' => 'ShopIt',
|
||||
'dominio' => 'admin.shopit.test',
|
||||
'scanner_domain' => 'scanner.shopit.test',
|
||||
'primary_color' => '#112233',
|
||||
'secondary_color' => '#445566',
|
||||
'danger_color' => '#aa0000',
|
||||
'success_color' => '#00aa00',
|
||||
'warning_color' => '#ffaa00',
|
||||
'body_color' => '#666666',
|
||||
'darker_body_color' => '#333333',
|
||||
'surface_color' => '#ffffff',
|
||||
'background_color' => '#f8f8f8',
|
||||
'border_color' => '#eaeaea',
|
||||
'login_header_footer_color' => '#313131',
|
||||
'site_logo' => $siteLogo->id,
|
||||
]);
|
||||
|
||||
$this->getJson('/api/v1/scanner/bootstrap/SCANNER.SHOPIT.TEST')
|
||||
->assertOk()
|
||||
->assertJsonPath('data.website_type_code', 'shopit')
|
||||
->assertJsonPath('data.primary_color', '#112233')
|
||||
->assertJsonPath('data.site_logo', $siteLogo->getTemporaryUrl(1440))
|
||||
->assertJsonPath('data.footer_logo', null)
|
||||
->assertJsonMissingPath('data.codigo')
|
||||
->assertJsonMissingPath('data.nombre')
|
||||
->assertJsonMissingPath('data.dominio')
|
||||
->assertJsonMissingPath('data.scanner_domain');
|
||||
}
|
||||
|
||||
public function test_it_does_not_match_the_admin_app_domain(): void
|
||||
{
|
||||
WebsiteType::query()->create([
|
||||
'codigo' => 'shopit',
|
||||
'nombre' => 'ShopIt',
|
||||
'dominio' => 'admin.shopit.test',
|
||||
'scanner_domain' => 'scanner.shopit.test',
|
||||
]);
|
||||
|
||||
$this->getJson('/api/v1/scanner/bootstrap/admin.shopit.test')
|
||||
->assertNotFound();
|
||||
}
|
||||
|
||||
public function test_it_returns_not_found_for_an_unknown_scanner_domain(): void
|
||||
{
|
||||
$this->getJson('/api/v1/scanner/bootstrap/unknown.test')
|
||||
->assertNotFound();
|
||||
}
|
||||
|
||||
public function test_it_rejects_an_invalid_domain(): void
|
||||
{
|
||||
$invalidDomain = str_repeat('a', 256);
|
||||
|
||||
$this->getJson("/api/v1/scanner/bootstrap/{$invalidDomain}")
|
||||
->assertUnprocessable()
|
||||
->assertJsonValidationErrors(['dominio']);
|
||||
}
|
||||
}
|
||||
@@ -20,6 +20,7 @@ class WebsiteTypeServiceTest extends TestCase
|
||||
'codigo' => 'marketplace',
|
||||
'nombre' => 'Marketplace',
|
||||
'dominio' => 'marketplace.test',
|
||||
'scanner_domain' => 'scanner.marketplace.test',
|
||||
'primary_color' => '#111111',
|
||||
'secondary_color' => '#222222',
|
||||
'danger_color' => '#ff0000',
|
||||
@@ -48,6 +49,7 @@ class WebsiteTypeServiceTest extends TestCase
|
||||
$this->assertDatabaseHas('website_type', [
|
||||
'codigo' => 'marketplace',
|
||||
'dominio' => 'marketplace.test',
|
||||
'scanner_domain' => 'scanner.marketplace.test',
|
||||
'warning_color' => '#ffaa00',
|
||||
'body_color' => '#666666',
|
||||
'darker_body_color' => '#333333',
|
||||
|
||||
Reference in New Issue
Block a user