diff --git a/src/Contracts/ManagesDatabaseUsers.php b/src/Contracts/ManagesDatabaseUsers.php index c92021e2..5c45391e 100644 --- a/src/Contracts/ManagesDatabaseUsers.php +++ b/src/Contracts/ManagesDatabaseUsers.php @@ -8,7 +8,7 @@ use Stancl\Tenancy\DatabaseConfig; interface ManagesDatabaseUsers { - public function createUser(DatabaseConfig $databaseConfig): void; + public function createUser(DatabaseConfig $databaseConfig): bool; - public function deleteUser(DatabaseConfig $databaseConfig): void; + public function deleteUser(DatabaseConfig $databaseConfig): bool; } diff --git a/src/Contracts/TenantDatabaseManager.php b/src/Contracts/TenantDatabaseManager.php index fb8e938f..55aefebf 100644 --- a/src/Contracts/TenantDatabaseManager.php +++ b/src/Contracts/TenantDatabaseManager.php @@ -4,6 +4,8 @@ declare(strict_types=1); namespace Stancl\Tenancy\Contracts; +use Stancl\Tenancy\Tenant; + interface TenantDatabaseManager { /** @@ -15,19 +17,13 @@ interface TenantDatabaseManager /** * Create a database. - * - * @param string $name Name of the database. - * @return bool */ - public function createDatabase(string $name): bool; + public function createDatabase(Tenant $tenant): bool; /** * Delete a database. - * - * @param string $name Name of the database. - * @return bool */ - public function deleteDatabase(string $name): bool; + public function deleteDatabase(Tenant $tenant): bool; /** * Does a database exist. diff --git a/src/DatabaseManager.php b/src/DatabaseManager.php index 44451fd6..0b32d72c 100644 --- a/src/DatabaseManager.php +++ b/src/DatabaseManager.php @@ -153,11 +153,7 @@ class DatabaseManager protected function createDatabaseSynchronously(Tenant $tenant, array $afterCreating) { $manager = $tenant->database()->manager(); - $manager->createDatabase($tenant->database()->getName()); - - if ($manager instanceof ManagesDatabaseUsers) { - $manager->createUser($tenant->database()); - } + $manager->createDatabase($tenant); foreach ($afterCreating as $item) { if (is_object($item) && ! $item instanceof Closure) { @@ -183,10 +179,7 @@ class DatabaseManager if ($this->app['config']['tenancy.queue_database_deletion'] ?? false) { QueuedTenantDatabaseDeleter::dispatch($manager, $tenant); } else { - $manager->deleteDatabase($database); - if ($manager instanceof ManagesDatabaseUsers) { - $manager->deleteUser($tenant->database()); - } + $manager->deleteDatabase($tenant); } $this->tenancy->event('database.deleted', $database, $tenant); diff --git a/src/Jobs/QueuedTenantDatabaseCreator.php b/src/Jobs/QueuedTenantDatabaseCreator.php index f081c212..15bcd15e 100644 --- a/src/Jobs/QueuedTenantDatabaseCreator.php +++ b/src/Jobs/QueuedTenantDatabaseCreator.php @@ -36,10 +36,6 @@ class QueuedTenantDatabaseCreator implements ShouldQueue */ public function handle() { - $this->databaseManager->createDatabase($this->databaseName); - - if ($this->databaseManager instanceof ManagesDatabaseUsers) { - $this->databaseManager->createUser($this->tenant->database()); - } + $this->databaseManager->createDatabase($this->tenant); } } diff --git a/src/Jobs/QueuedTenantDatabaseDeleter.php b/src/Jobs/QueuedTenantDatabaseDeleter.php index 0912755c..b772ab56 100644 --- a/src/Jobs/QueuedTenantDatabaseDeleter.php +++ b/src/Jobs/QueuedTenantDatabaseDeleter.php @@ -36,9 +36,6 @@ class QueuedTenantDatabaseDeleter implements ShouldQueue */ public function handle() { - $this->databaseManager->deleteDatabase($this->tenant->database()->getName()); - if ($this->databaseManager instanceof ManagesDatabaseUsers) { - $this->databaseManager->deleteUser($this->tenant->database()); - } + $this->databaseManager->deleteDatabase($this->tenant); } } diff --git a/src/TenantDatabaseManagers/MySQLDatabaseManager.php b/src/TenantDatabaseManagers/MySQLDatabaseManager.php index 5c1a7123..2685b527 100644 --- a/src/TenantDatabaseManagers/MySQLDatabaseManager.php +++ b/src/TenantDatabaseManagers/MySQLDatabaseManager.php @@ -9,6 +9,7 @@ use Illuminate\Database\Connection; use Illuminate\Support\Facades\DB; use Stancl\Tenancy\Contracts\Future\CanSetConnection; use Stancl\Tenancy\Contracts\TenantDatabaseManager; +use Stancl\Tenancy\Tenant; class MySQLDatabaseManager implements TenantDatabaseManager, CanSetConnection { @@ -35,17 +36,18 @@ class MySQLDatabaseManager implements TenantDatabaseManager, CanSetConnection $this->connection = $connection; } - public function createDatabase(string $name): bool + public function createDatabase(Tenant $tenant): bool { + $database = $tenant->database()->getName(); $charset = $this->database()->getConfig('charset'); $collation = $this->database()->getConfig('collation'); - return $this->database()->statement("CREATE DATABASE `$name` CHARACTER SET `$charset` COLLATE `$collation`"); + return $this->database()->statement("CREATE DATABASE `{$database}` CHARACTER SET `$charset` COLLATE `$collation`"); } - public function deleteDatabase(string $name): bool + public function deleteDatabase(Tenant $tenant): bool { - return $this->database()->statement("DROP DATABASE `$name`"); + return $this->database()->statement("DROP DATABASE `{$tenant->database()->getName()}`"); } public function databaseExists(string $name): bool diff --git a/src/TenantDatabaseManagers/PermissionControlledMySQLDatabaseManager.php b/src/TenantDatabaseManagers/PermissionControlledMySQLDatabaseManager.php index 89b9b778..12872b73 100644 --- a/src/TenantDatabaseManagers/PermissionControlledMySQLDatabaseManager.php +++ b/src/TenantDatabaseManagers/PermissionControlledMySQLDatabaseManager.php @@ -6,16 +6,19 @@ namespace Stancl\Tenancy\TenantDatabaseManagers; use Stancl\Tenancy\Contracts\ManagesDatabaseUsers; use Stancl\Tenancy\DatabaseConfig; +use Stancl\Tenancy\Traits\CreatesDatabaseUsers; class PermissionControlledMySQLDatabaseManager extends MySQLDatabaseManager implements ManagesDatabaseUsers { + use CreatesDatabaseUsers; + public static $grants = [ 'ALTER', 'ALTER ROUTINE', 'CREATE', 'CREATE ROUTINE', 'CREATE TEMPORARY TABLES', 'CREATE VIEW', 'DELETE', 'DROP', 'EVENT', 'EXECUTE', 'INDEX', 'INSERT', 'LOCK TABLES', 'REFERENCES', 'SELECT', 'SHOW VIEW', 'TRIGGER', 'UPDATE', ]; - public function createUser(DatabaseConfig $databaseConfig): void + public function createUser(DatabaseConfig $databaseConfig): bool { $database = $databaseConfig->getName(); $username = $databaseConfig->getUsername(); @@ -32,7 +35,7 @@ class PermissionControlledMySQLDatabaseManager extends MySQLDatabaseManager impl $grantQuery = "GRANT $grants ON $database.* TO `$username`@`$hostname` IDENTIFIED BY '$password'"; } - $this->database()->statement($grantQuery); + return $this->database()->statement($grantQuery); } protected function isVersion8(): bool @@ -42,8 +45,8 @@ class PermissionControlledMySQLDatabaseManager extends MySQLDatabaseManager impl return version_compare($version, '8.0.0') >= 0; } - public function deleteUser(DatabaseConfig $databaseConfig): void + public function deleteUser(DatabaseConfig $databaseConfig): bool { - $this->database()->statement("DROP USER IF EXISTS '{$databaseConfig->username}'"); + return $this->database()->statement("DROP USER IF EXISTS '{$databaseConfig->username}'"); } } diff --git a/src/TenantDatabaseManagers/PostgreSQLDatabaseManager.php b/src/TenantDatabaseManagers/PostgreSQLDatabaseManager.php index b83ae688..f189e232 100644 --- a/src/TenantDatabaseManagers/PostgreSQLDatabaseManager.php +++ b/src/TenantDatabaseManagers/PostgreSQLDatabaseManager.php @@ -9,6 +9,7 @@ use Illuminate\Database\Connection; use Illuminate\Support\Facades\DB; use Stancl\Tenancy\Contracts\Future\CanSetConnection; use Stancl\Tenancy\Contracts\TenantDatabaseManager; +use Stancl\Tenancy\Tenant; class PostgreSQLDatabaseManager implements TenantDatabaseManager, CanSetConnection { @@ -35,14 +36,14 @@ class PostgreSQLDatabaseManager implements TenantDatabaseManager, CanSetConnecti $this->connection = $connection; } - public function createDatabase(string $name): bool + public function createDatabase(Tenant $tenant): bool { - return $this->database()->statement("CREATE DATABASE \"$name\" WITH TEMPLATE=template0"); + return $this->database()->statement("CREATE DATABASE \"{$tenant->database()->getName()}\" WITH TEMPLATE=template0"); } - public function deleteDatabase(string $name): bool + public function deleteDatabase(Tenant $tenant): bool { - return $this->database()->statement("DROP DATABASE \"$name\""); + return $this->database()->statement("DROP DATABASE \"{$tenant->database()->getName()}\""); } public function databaseExists(string $name): bool diff --git a/src/TenantDatabaseManagers/PostgreSQLSchemaManager.php b/src/TenantDatabaseManagers/PostgreSQLSchemaManager.php index 14c05cf0..819daf09 100644 --- a/src/TenantDatabaseManagers/PostgreSQLSchemaManager.php +++ b/src/TenantDatabaseManagers/PostgreSQLSchemaManager.php @@ -9,6 +9,7 @@ use Illuminate\Database\Connection; use Illuminate\Support\Facades\DB; use Stancl\Tenancy\Contracts\Future\CanSetConnection; use Stancl\Tenancy\Contracts\TenantDatabaseManager; +use Stancl\Tenancy\Tenant; class PostgreSQLSchemaManager implements TenantDatabaseManager, CanSetConnection { @@ -35,14 +36,14 @@ class PostgreSQLSchemaManager implements TenantDatabaseManager, CanSetConnection $this->connection = $connection; } - public function createDatabase(string $name): bool + public function createDatabase(Tenant $tenant): bool { - return $this->database()->statement("CREATE SCHEMA \"$name\""); + return $this->database()->statement("CREATE SCHEMA \"{$tenant->database()->getName()}\""); } - public function deleteDatabase(string $name): bool + public function deleteDatabase(Tenant $tenant): bool { - return $this->database()->statement("DROP SCHEMA \"$name\""); + return $this->database()->statement("DROP SCHEMA \"{$tenant->database()->getName()}\""); } public function databaseExists(string $name): bool diff --git a/src/TenantDatabaseManagers/SQLiteDatabaseManager.php b/src/TenantDatabaseManagers/SQLiteDatabaseManager.php index 20d60665..19407ce9 100644 --- a/src/TenantDatabaseManagers/SQLiteDatabaseManager.php +++ b/src/TenantDatabaseManagers/SQLiteDatabaseManager.php @@ -6,6 +6,7 @@ namespace Stancl\Tenancy\TenantDatabaseManagers; use Stancl\Tenancy\Contracts\ModifiesDatabaseNameForConnection; use Stancl\Tenancy\Contracts\TenantDatabaseManager; +use Stancl\Tenancy\Tenant; class SQLiteDatabaseManager implements TenantDatabaseManager, ModifiesDatabaseNameForConnection { @@ -14,19 +15,19 @@ class SQLiteDatabaseManager implements TenantDatabaseManager, ModifiesDatabaseNa return 'database'; } - public function createDatabase(string $name): bool + public function createDatabase(Tenant $tenant): bool { try { - return fclose(fopen(database_path($name), 'w')); + return fclose(fopen(database_path($tenant->database()->getName()), 'w')); } catch (\Throwable $th) { return false; } } - public function deleteDatabase(string $name): bool + public function deleteDatabase(Tenant $tenant): bool { try { - return unlink(database_path($name)); + return unlink(database_path($tenant->database()->getName())); } catch (\Throwable $th) { return false; } diff --git a/src/Traits/CreatesDatabaseUsers.php b/src/Traits/CreatesDatabaseUsers.php new file mode 100644 index 00000000..249ddcb1 --- /dev/null +++ b/src/Traits/CreatesDatabaseUsers.php @@ -0,0 +1,26 @@ +database()->transaction(function () use ($tenant) { + parent::createDatabase($tenant); + + return $this->createUser($tenant->database()); + }); + } + + public function deleteDatabase(Tenant $tenant): bool + { + return $this->database()->transaction(function () use ($tenant) { + parent::deleteDatabase($tenant); + + return $this->deleteUser($tenant->database()); + }); + } +} \ No newline at end of file diff --git a/tests/TenantDatabaseManagerTest.php b/tests/TenantDatabaseManagerTest.php index 89c0bbd7..7445374e 100644 --- a/tests/TenantDatabaseManagerTest.php +++ b/tests/TenantDatabaseManagerTest.php @@ -9,6 +9,7 @@ use Stancl\Tenancy\Jobs\QueuedTenantDatabaseCreator; use Stancl\Tenancy\Jobs\QueuedTenantDatabaseDeleter; use Stancl\Tenancy\Tenant; use Stancl\Tenancy\TenantDatabaseManagers\MySQLDatabaseManager; +use Stancl\Tenancy\TenantDatabaseManagers\PermissionControlledMySQLDatabaseManager; use Stancl\Tenancy\TenantDatabaseManagers\PostgreSQLDatabaseManager; use Stancl\Tenancy\TenantDatabaseManagers\PostgreSQLSchemaManager; use Stancl\Tenancy\TenantDatabaseManagers\SQLiteDatabaseManager; @@ -77,6 +78,7 @@ class TenantDatabaseManagerTest extends TestCase { return [ ['mysql', MySQLDatabaseManager::class], + ['mysql', PermissionControlledMySQLDatabaseManager::class], ['sqlite', SQLiteDatabaseManager::class], ['pgsql', PostgreSQLDatabaseManager::class], ['pgsql', PostgreSQLSchemaManager::class],