From f603a82b5ef3a4aeb0e2a44ad6bdf99da0ed58e1 Mon Sep 17 00:00:00 2001 From: ncoronel Date: Fri, 31 Jul 2026 13:39:31 -0300 Subject: [PATCH] feat(website-type): implement BootstrapWebsiteTypeController and related request/resource for domain-based bootstrapping --- .../AdminApp/BootstrapAdminAppController.php | 25 ++++++++ .../Requests/BootstrapAdminAppRequest.php | 5 ++ .../AdminApp/BootstrapAdminAppResource.php | 38 +++++++++++++ app/Domains/Tenant/routes/adminapp.php | 6 ++ database/seeders/WebsiteTypeSeeder.php | 2 + .../Feature/Seeders/WebsiteTypeSeederTest.php | 2 + .../BootstrapAdminAppControllerTest.php | 57 +++++++++++++++++++ .../Tenant/BootstrapAdminAppResourceTest.php | 25 ++++++++ 8 files changed, 160 insertions(+) create mode 100644 app/Domains/Tenant/Controllers/AdminApp/BootstrapAdminAppController.php create mode 100644 app/Domains/Tenant/Requests/BootstrapAdminAppRequest.php create mode 100644 app/Domains/Tenant/Resources/AdminApp/BootstrapAdminAppResource.php create mode 100644 tests/Feature/Tenant/BootstrapAdminAppControllerTest.php create mode 100644 tests/Unit/Tenant/BootstrapAdminAppResourceTest.php diff --git a/app/Domains/Tenant/Controllers/AdminApp/BootstrapAdminAppController.php b/app/Domains/Tenant/Controllers/AdminApp/BootstrapAdminAppController.php new file mode 100644 index 0000000..9f67771 --- /dev/null +++ b/app/Domains/Tenant/Controllers/AdminApp/BootstrapAdminAppController.php @@ -0,0 +1,25 @@ +validated('dominio'); + + return BootstrapAdminAppResource::make( + WebsiteType::query() + ->with('siteLogo') + ->where('dominio', $domain) + ->firstOrFail() + ); + } +} diff --git a/app/Domains/Tenant/Requests/BootstrapAdminAppRequest.php b/app/Domains/Tenant/Requests/BootstrapAdminAppRequest.php new file mode 100644 index 0000000..c07bf9f --- /dev/null +++ b/app/Domains/Tenant/Requests/BootstrapAdminAppRequest.php @@ -0,0 +1,5 @@ + + */ + public function toArray(Request $request): array + { + return [ + 'codigo' => $this->codigo, + 'website_type_code' => $this->codigo, + 'nombre' => $this->nombre, + 'dominio' => $this->dominio, + 'primary_color' => $this->primary_color, + 'secondary_color' => $this->secondary_color, + 'danger_color' => $this->danger_color, + 'success_color' => $this->success_color, + 'warning_color' => $this->warning_color, + 'body_color' => $this->body_color, + 'darker_body_color' => $this->darker_body_color, + 'surface_color' => $this->surface_color, + 'background_color' => $this->background_color, + 'border_color' => $this->border_color, + 'login_header_footer_color' => $this->login_header_footer_color, + 'site_logo' => $this->siteLogo?->getTemporaryUrl(1440), + ]; + } +} diff --git a/app/Domains/Tenant/routes/adminapp.php b/app/Domains/Tenant/routes/adminapp.php index f5ef025..08a47e8 100644 --- a/app/Domains/Tenant/routes/adminapp.php +++ b/app/Domains/Tenant/routes/adminapp.php @@ -1,9 +1,15 @@ middleware(['auth:sanctum', 'adminapp.tenant']) ->group(function (): void { diff --git a/database/seeders/WebsiteTypeSeeder.php b/database/seeders/WebsiteTypeSeeder.php index c1e75ec..71a8c81 100644 --- a/database/seeders/WebsiteTypeSeeder.php +++ b/database/seeders/WebsiteTypeSeeder.php @@ -30,6 +30,7 @@ class WebsiteTypeSeeder extends Seeder ['codigo' => 'shopit'], [ 'nombre' => 'ShopIt', + 'dominio' => 'localhost', ...self::PRESENTATION, 'site_logo' => $this->onTicketLogo(), ], @@ -60,6 +61,7 @@ class WebsiteTypeSeeder extends Seeder ['codigo' => 'onticket'], [ 'nombre' => 'OnTicket', + 'dominio' => 'onticket.localhost', ...self::PRESENTATION, 'site_logo' => $this->onTicketLogo(), ], diff --git a/tests/Feature/Seeders/WebsiteTypeSeederTest.php b/tests/Feature/Seeders/WebsiteTypeSeederTest.php index 54c2132..47a93a6 100644 --- a/tests/Feature/Seeders/WebsiteTypeSeederTest.php +++ b/tests/Feature/Seeders/WebsiteTypeSeederTest.php @@ -42,6 +42,7 @@ class WebsiteTypeSeederTest extends TestCase ->sole(); $this->assertSame('ShopIt', $shopIt->nombre); + $this->assertSame('localhost', $shopIt->dominio); $this->assertSame($expectedPresentation, $shopIt->only(array_keys($expectedPresentation))); $this->assertSame('onticket_logo.png', $shopIt->siteLogo->filename); Storage::disk('s3')->assertExists($shopIt->siteLogo->path); @@ -66,6 +67,7 @@ class WebsiteTypeSeederTest extends TestCase ->sole(); $this->assertSame('OnTicket', $onTicket->nombre); + $this->assertSame('onticket.localhost', $onTicket->dominio); $this->assertSame($expectedPresentation, $onTicket->only(array_keys($expectedPresentation))); $this->assertSame('onticket_logo.png', $onTicket->siteLogo->filename); Storage::disk('s3')->assertExists($onTicket->siteLogo->path); diff --git a/tests/Feature/Tenant/BootstrapAdminAppControllerTest.php b/tests/Feature/Tenant/BootstrapAdminAppControllerTest.php new file mode 100644 index 0000000..be5b07a --- /dev/null +++ b/tests/Feature/Tenant/BootstrapAdminAppControllerTest.php @@ -0,0 +1,57 @@ +create([ + 'codigo' => 'shopit', + 'nombre' => 'ShopIt', + 'dominio' => 'admin.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', + ]); + + $this->getJson('/api/v1/adminapp/bootstrap/ADMIN.SHOPIT.TEST') + ->assertOk() + ->assertJsonPath('data.codigo', 'shopit') + ->assertJsonPath('data.website_type_code', 'shopit') + ->assertJsonPath('data.dominio', 'admin.shopit.test') + ->assertJsonPath('data.primary_color', '#112233') + ->assertJsonPath('data.warning_color', '#ffaa00') + ->assertJsonPath('data.login_header_footer_color', '#313131') + ->assertJsonPath('data.site_logo', null); + } + + public function test_it_returns_not_found_for_an_unknown_domain(): void + { + $this->getJson('/api/v1/adminapp/bootstrap/unknown.test') + ->assertNotFound(); + } + + public function test_it_rejects_an_invalid_domain(): void + { + $invalidDomain = str_repeat('a', 256); + + $this->getJson("/api/v1/adminapp/bootstrap/{$invalidDomain}") + ->assertUnprocessable() + ->assertJsonValidationErrors(['dominio']); + } +} diff --git a/tests/Unit/Tenant/BootstrapAdminAppResourceTest.php b/tests/Unit/Tenant/BootstrapAdminAppResourceTest.php new file mode 100644 index 0000000..f9dfdb6 --- /dev/null +++ b/tests/Unit/Tenant/BootstrapAdminAppResourceTest.php @@ -0,0 +1,25 @@ + 'shopit', + 'nombre' => 'ShopIt', + 'dominio' => 'admin.shopit.test', + ]); + $websiteType->setRelation('siteLogo', null); + + $data = BootstrapAdminAppResource::make($websiteType)->resolve(request()); + + $this->assertSame('shopit', $data['codigo']); + $this->assertSame('shopit', $data['website_type_code']); + } +}