Add BootstrapTenantController and requests for tenant domain normalization; implement API route and tests

This commit is contained in:
2026-06-23 09:49:54 -03:00
parent 6d83d3dd7d
commit 3c6469617b
10 changed files with 399 additions and 34 deletions

View File

@@ -1,29 +0,0 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('tenant_props', function (Blueprint $table) {
$table->id();
$table->string('codigo')->unique();
$table->string('prop_type');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('tenant_props');
}
};

View File

@@ -0,0 +1,107 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
$normalizedDomains = [];
$duplicateTenantIdsByDomain = [];
$tenants = DB::table('tenants')
->select(['id', 'dominio'])
->orderBy('id')
->get();
foreach ($tenants as $tenant) {
$normalizedDomain = $this->normalizeDomain($tenant->dominio, $tenant->id);
if ($normalizedDomain === null) {
continue;
}
$normalizedDomains[$tenant->id] = $normalizedDomain;
$duplicateTenantIdsByDomain[$normalizedDomain][] = $tenant->id;
}
$duplicates = array_filter(
$duplicateTenantIdsByDomain,
static fn (array $tenantIds): bool => count($tenantIds) > 1,
);
if ($duplicates !== []) {
$duplicateSummary = array_map(
static fn (string $domain, array $tenantIds): string => sprintf(
'%s => [%s]',
$domain,
implode(', ', $tenantIds),
),
array_keys($duplicates),
array_values($duplicates),
);
throw new RuntimeException(
'Cannot create a unique index for tenants.dominio because normalized duplicates exist: '
.implode('; ', $duplicateSummary)
);
}
foreach ($normalizedDomains as $tenantId => $normalizedDomain) {
DB::table('tenants')
->where('id', $tenantId)
->update(['dominio' => $normalizedDomain]);
}
Schema::table('tenants', function (Blueprint $table) {
$table->unique('dominio', 'tenants_dominio_unique');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('tenants', function (Blueprint $table) {
$table->dropUnique('tenants_dominio_unique');
});
}
private function normalizeDomain(mixed $domain, int $tenantId): ?string
{
if ($domain === null) {
return null;
}
if (! is_string($domain)) {
throw new RuntimeException("Cannot normalize tenant domain for tenant {$tenantId}.");
}
$decodedDomain = trim(urldecode($domain));
if ($decodedDomain === '') {
return null;
}
$candidate = str_contains($decodedDomain, '://')
? $decodedDomain
: "//{$decodedDomain}";
$host = parse_url($candidate, PHP_URL_HOST);
if (! is_string($host) || $host === '') {
throw new RuntimeException(
"Cannot normalize tenant domain '{$domain}' for tenant {$tenantId}."
);
}
return strtolower($host);
}
};