Add BootstrapTenantController and requests for tenant domain normalization; implement API route and tests
This commit is contained in:
@@ -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');
|
||||
}
|
||||
};
|
||||
@@ -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);
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user