feat: Provisionner automatiquement un nouvel établissement
Lorsqu'un super-admin crée un établissement via l'interface, le système doit automatiquement créer la base tenant, exécuter les migrations, créer le premier utilisateur admin et envoyer l'invitation — le tout de manière asynchrone pour ne pas bloquer la réponse HTTP. Ce mécanisme rend chaque établissement opérationnel dès sa création sans intervention manuelle sur l'infrastructure.
This commit is contained in:
@@ -8,6 +8,7 @@ use App\Scolarite\Application\Port\FileStorage;
|
||||
|
||||
use function dirname;
|
||||
use function file_put_contents;
|
||||
use function fopen;
|
||||
use function is_dir;
|
||||
use function is_file;
|
||||
use function is_string;
|
||||
@@ -15,6 +16,12 @@ use function mkdir;
|
||||
|
||||
use Override;
|
||||
|
||||
use function realpath;
|
||||
|
||||
use RuntimeException;
|
||||
|
||||
use function sprintf;
|
||||
use function str_starts_with;
|
||||
use function unlink;
|
||||
|
||||
final readonly class LocalFileStorage implements FileStorage
|
||||
@@ -50,4 +57,24 @@ final readonly class LocalFileStorage implements FileStorage
|
||||
unlink($fullPath);
|
||||
}
|
||||
}
|
||||
|
||||
#[Override]
|
||||
public function readStream(string $path): mixed
|
||||
{
|
||||
$fullPath = $this->storagePath . '/' . $path;
|
||||
$realPath = realpath($fullPath);
|
||||
$realStoragePath = realpath($this->storagePath);
|
||||
|
||||
if ($realPath === false || $realStoragePath === false || !str_starts_with($realPath, $realStoragePath)) {
|
||||
throw new RuntimeException(sprintf('Impossible de lire le fichier : %s', $path));
|
||||
}
|
||||
|
||||
$stream = fopen($realPath, 'r');
|
||||
|
||||
if ($stream === false) {
|
||||
throw new RuntimeException(sprintf('Impossible de lire le fichier : %s', $path));
|
||||
}
|
||||
|
||||
return $stream;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user