- Mandantenauswahl fuer Benutzer mit mehreren Tenants bauen - feste Tenant-Domains ohne Wildcard-Abhaengigkeit vorbereiten - Login, Backfill, Smoke-Checks und M3-Dokumentation aktualisieren
122 lines
4.7 KiB
PHP
122 lines
4.7 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
require __DIR__ . '/dev-db.php';
|
|
require __DIR__ . '/../app/saas-auth.php';
|
|
|
|
function tenant_resolution_assert(string $label, bool $condition, array &$failures, int &$passes): void
|
|
{
|
|
if ($condition) {
|
|
$passes++;
|
|
echo "PASS {$label}\n";
|
|
return;
|
|
}
|
|
|
|
$failures[] = $label;
|
|
echo "FAIL {$label}\n";
|
|
}
|
|
|
|
function tenant_resolution_cleanup(PDO $pdo, array $slugs, string $emailNorm): void
|
|
{
|
|
foreach ($slugs as $slug) {
|
|
$stmt = $pdo->prepare('SELECT id FROM tenants WHERE slug = ?');
|
|
$stmt->execute([$slug]);
|
|
$tenantId = $stmt->fetchColumn();
|
|
|
|
if ($tenantId === false) {
|
|
continue;
|
|
}
|
|
|
|
$tenantId = (int)$tenantId;
|
|
$pdo->prepare('DELETE FROM tenant_domains WHERE tenant_id = ?')->execute([$tenantId]);
|
|
$pdo->prepare('DELETE FROM participants WHERE tenant_id = ?')->execute([$tenantId]);
|
|
$pdo->prepare('DELETE FROM tenant_memberships WHERE tenant_id = ?')->execute([$tenantId]);
|
|
$pdo->prepare('DELETE FROM tenant_settings WHERE tenant_id = ?')->execute([$tenantId]);
|
|
$pdo->prepare('DELETE FROM tenants WHERE id = ?')->execute([$tenantId]);
|
|
}
|
|
|
|
$pdo->prepare('DELETE FROM users WHERE email_norm = ?')->execute([$emailNorm]);
|
|
}
|
|
|
|
$pdo = dev_pdo();
|
|
dev_apply_schema($pdo);
|
|
|
|
$slugs = ['m3-tenant-choice-a', 'm3-tenant-choice-b'];
|
|
$email = 'm3-tenant-choice@test.local';
|
|
$emailNorm = saas_email_norm($email);
|
|
$password = 'M3-tenant-choice-123';
|
|
$failures = [];
|
|
$passes = 0;
|
|
|
|
tenant_resolution_cleanup($pdo, $slugs, $emailNorm);
|
|
|
|
$first = saas_register_tenant_owner($pdo, [
|
|
'tenant_name' => 'M3 Tenant Choice A',
|
|
'tenant_slug' => $slugs[0],
|
|
'display_name' => 'M3 Tenant Choice',
|
|
'email' => $email,
|
|
'password' => $password,
|
|
'password_confirm' => $password,
|
|
]);
|
|
$second = saas_register_tenant_owner($pdo, [
|
|
'tenant_name' => 'M3 Tenant Choice B',
|
|
'tenant_slug' => $slugs[1],
|
|
'display_name' => 'M3 Tenant Choice',
|
|
'email' => $email,
|
|
'password' => $password,
|
|
'password_confirm' => $password,
|
|
]);
|
|
|
|
tenant_resolution_assert('first registration succeeds', $first['ok'] === true, $failures, $passes);
|
|
tenant_resolution_assert('second registration succeeds', $second['ok'] === true, $failures, $passes);
|
|
|
|
if ($first['ok'] && $second['ok']) {
|
|
$userId = (int)$first['identity']['user_id'];
|
|
$memberships = saas_list_user_memberships($pdo, $userId);
|
|
tenant_resolution_assert('user has two memberships', count($memberships) === 2, $failures, $passes);
|
|
|
|
$genericLogin = saas_authenticate($pdo, $email, $password);
|
|
tenant_resolution_assert('generic login succeeds', $genericLogin['ok'] === true, $failures, $passes);
|
|
tenant_resolution_assert('generic login needs tenant selection', !empty($genericLogin['needs_tenant_selection']), $failures, $passes);
|
|
tenant_resolution_assert('generic login exposes memberships', count($genericLogin['memberships'] ?? []) === 2, $failures, $passes);
|
|
|
|
$specificLogin = saas_authenticate($pdo, $email, $password, $slugs[1]);
|
|
tenant_resolution_assert('specific login succeeds', $specificLogin['ok'] === true, $failures, $passes);
|
|
tenant_resolution_assert(
|
|
'specific login selects requested tenant',
|
|
($specificLogin['identity']['tenant_slug'] ?? null) === $slugs[1],
|
|
$failures,
|
|
$passes
|
|
);
|
|
|
|
$identity = saas_identity_for_user_tenant($pdo, $userId, (int)$second['identity']['tenant_id']);
|
|
tenant_resolution_assert('tenant selection identity exists', $identity !== null, $failures, $passes);
|
|
if ($identity !== null) {
|
|
tenant_resolution_assert('tenant selection returns requested tenant', $identity['tenant_slug'] === $slugs[1], $failures, $passes);
|
|
}
|
|
|
|
$pdo->prepare(
|
|
'INSERT INTO tenant_domains (tenant_id, domain, domain_norm, domain_type, status, verified_at)
|
|
VALUES (?, ?, ?, ?, ?, NOW())'
|
|
)->execute([(int)$second['identity']['tenant_id'], 'kaffee.example.test', 'kaffee.example.test', 'custom', 'active']);
|
|
|
|
$domainTenant = saas_resolve_tenant_domain($pdo, 'kaffee.example.test:443');
|
|
tenant_resolution_assert('fixed domain resolves tenant', $domainTenant !== null, $failures, $passes);
|
|
if ($domainTenant !== null) {
|
|
tenant_resolution_assert('fixed domain returns requested tenant', $domainTenant['tenant_slug'] === $slugs[1], $failures, $passes);
|
|
}
|
|
}
|
|
|
|
tenant_resolution_cleanup($pdo, $slugs, $emailNorm);
|
|
|
|
if ($failures !== []) {
|
|
echo "\nM3 tenant resolution check failed with " . count($failures) . " failure(s):\n";
|
|
foreach ($failures as $failure) {
|
|
echo "- {$failure}\n";
|
|
}
|
|
exit(1);
|
|
}
|
|
|
|
echo "\nM3 tenant resolution check passed with {$passes} assertions.\n";
|