diff --git a/assets/config.php b/assets/config.php index 844b8d93..a5d89ad8 100644 --- a/assets/config.php +++ b/assets/config.php @@ -100,7 +100,7 @@ return [ * The connection that will be used as a template for the dynamically created tenant connection. * Set to null to use the default connection. */ - 'based_on' => null, + 'template_connection' => null, /** * Tenant database names are created like this: @@ -108,8 +108,6 @@ return [ */ 'prefix' => 'tenant', 'suffix' => '', - - 'separate_by' => 'database', // database or schema (only supported by pgsql) ], /** @@ -197,9 +195,14 @@ return [ 'pgsql' => Stancl\Tenancy\TenantDatabaseManagers\PostgreSQLDatabaseManager::class, /** - * Disable the pgsql manager above, enable the one below, and set the - * tenancy.database.separate_by config key to 'schema' if you would - * like to separate tenant DBs by schemas rather than databases. + * Use this database manager for MySQL to have a DB user created for each tenant database. + * You can customize the grants given to these users by changing the $grants property. + */ + // 'mysql' => Stancl\Tenancy\TenantDatabaseManagers\PermissionControlledMySQLDatabaseManager::class, + + /** + * Disable the pgsql manager above, and enable the one below if you + * want to separate tenant DBs by schemas rather than databases. */ // 'pgsql' => Stancl\Tenancy\TenantDatabaseManagers\PostgreSQLSchemaManager::class, // Separate by schema instead of database ], diff --git a/src/Contracts/ManagesDatabaseUsers.php b/src/Contracts/ManagesDatabaseUsers.php new file mode 100644 index 00000000..d9167f29 --- /dev/null +++ b/src/Contracts/ManagesDatabaseUsers.php @@ -0,0 +1,11 @@ +id . config('tenancy.database.suffix'); + }; + } + + public function __construct(Tenant $tenant) + { + static::__constructStatic(); + + $this->tenant = $tenant; + } + + public static function generateDatabaseNameUsing(callable $databaseNameGenerator): void + { + static::$databaseNameGenerator = $databaseNameGenerator; + } + + public static function generateUsernameUsing(callable $usernameGenerator): void + { + static::$usernameGenerator = $usernameGenerator; + } + + public static function generatePasswordUsing(callable $passwordGenerator): void + { + static::$passwordGenerator = $passwordGenerator; + } + + public function getName(): string + { + return $this->tenant->data['_tenancy_db_name']; + } + + public function getUsername(): string + { + return $this->tenant->data['_tenancy_db_username']; + } + + public function getPassword(): string + { + return $this->tenant->data['_tenancy_db_password']; + } + + public function getTemplateDatabaseConnection(): string + { + return $this->tenant->data['_tenancy_db_connection']; + } + + public function makeCredentials(): void + { + $this->tenant->data['_tenancy_db_name'] = $this->getName() ?? (static::$databaseNameGenerator)($this->tenant); + + if ($this->manager() instanceof ManagesDatabaseUsers) { + $this->tenant->data['_tenancy_db_username'] = $this->getUsername() ?? (static::$usernameGenerator)($this->tenant); + $this->tenant->data['_tenancy_db_password'] = $this->getPassword() ?? (static::$passwordGenerator)($this->tenant); + } + + $this->tenant->save(); + } + + /** + * Template used to construct the tenant connection. Also serves as + * the root connection on which the tenant database is created. + */ + public function getTemplateConnectionName() + { + $name = $this->tenant->getTemplateDatabaseConnection(); + + // If we're using e.g. 'tenant', the default, template connection + // and it doesn't exist, we'll go for the default DB template. + if (! array_key_exists($name, config('database.connections'))) { + $name = config('tenancy.database.template_connection') ?? DatabaseManager::$originalDefaultConnectionName; + }; + + return $name; + } + + /** + * Tenant's own database connection config. + */ + public function connection(): array + { + $templateConnection = config("database.connections.{$this->getTemplateConnectionName()}"); + + return array_merge($templateConnection, $this->tenantConfig(), [ + $this->manager()->getSeparator() => $this->tenant->database()->getName(), + ]); + } + + /** + * Additional config for the database connection, specific to this tenant. + */ + public function tenantConfig(): array + { + $dbConfig = array_filter(array_keys($this->tenant->data), function ($key) { + return Str::startsWith($key, '_tenancy_db_'); + }); + + // Remove DB name because we set that separately + if (isset($dbConfig['_tenancy_db_name'])) { + unset($dbConfig['_tenancy_db_name']); + } + + return array_reduce($dbConfig, function ($config, $key) { + return array_merge($config, [ + Str::substr($key, 0, strlen('_tenancy_db_')) => $this->tenant[$key], + ]); + }, []); + } + + /** + * Get the TenantDatabaseManager for this tenant's connection. + */ + public function manager(): TenantDatabaseManager + { + $driver = config("database.connections.{$this->getTemplateConnectionName()}.driver"); + + $databaseManagers = config('tenancy.database_managers'); + + if (! array_key_exists($driver, $databaseManagers)) { + throw new DatabaseManagerNotRegisteredException($driver); + } + + /** @var TenantDatabaseManager $databaseManager */ + $databaseManager = app($databaseManagers[$driver]); + + if ($databaseManager instanceof CanSetConnection) { + $databaseManager->setConnection($this->getTemplateConnectionName()); + } + + return $databaseManager; + } +} diff --git a/src/DatabaseManager.php b/src/DatabaseManager.php index 0004ea69..93c5feab 100644 --- a/src/DatabaseManager.php +++ b/src/DatabaseManager.php @@ -8,18 +8,20 @@ use Closure; use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Database\DatabaseManager as BaseDatabaseManager; use Illuminate\Foundation\Application; -use Stancl\Tenancy\Contracts\Future\CanSetConnection; +use Stancl\Tenancy\Contracts\ManagesDatabaseUsers; use Stancl\Tenancy\Contracts\TenantCannotBeCreatedException; -use Stancl\Tenancy\Contracts\TenantDatabaseManager; use Stancl\Tenancy\Exceptions\DatabaseManagerNotRegisteredException; use Stancl\Tenancy\Exceptions\TenantDatabaseAlreadyExistsException; use Stancl\Tenancy\Jobs\QueuedTenantDatabaseCreator; use Stancl\Tenancy\Jobs\QueuedTenantDatabaseDeleter; +/** + * @internal Class is subject to breaking changes in minor and patch versions. + */ class DatabaseManager { /** @var string */ - public $originalDefaultConnectionName; + public static $originalDefaultConnectionName; /** @var Application */ protected $app; @@ -34,14 +36,11 @@ class DatabaseManager { $this->app = $app; $this->database = $database; - $this->originalDefaultConnectionName = $app['config']['database.default']; + static::$originalDefaultConnectionName = $app['config']['database.default']; } /** * Set the TenantManager instance, used to dispatch tenancy events. - * - * @param TenantManager $tenantManager - * @return self */ public function withTenantManager(TenantManager $tenantManager): self { @@ -52,21 +51,16 @@ class DatabaseManager /** * Connect to a tenant's database. - * - * @param Tenant $tenant - * @return void */ public function connect(Tenant $tenant) { - $this->createTenantConnection($tenant->getDatabaseName(), $tenant->getConnectionName()); + $this->createTenantConnection($tenant, $tenant->getConnectionName()); $this->setDefaultConnection($tenant->getConnectionName()); $this->switchConnection($tenant->getConnectionName()); } /** * Reconnect to the default non-tenant connection. - * - * @return void */ public function reconnect() { @@ -78,9 +72,6 @@ class DatabaseManager /** * Change the default database connection config. - * - * @param string $connection - * @return void */ public function setDefaultConnection(string $connection) { @@ -89,53 +80,14 @@ class DatabaseManager /** * Create the tenant database connection. - * - * @param string $databaseName - * @param string $connectionName - * @return void */ - public function createTenantConnection($databaseName, $connectionName) + public function createTenantConnection(Tenant $tenant, $connectionName) { - // Create the database connection. - $based_on = $this->getBaseConnection($connectionName); - $this->app['config']["database.connections.$connectionName"] = $this->app['config']['database.connections.' . $based_on]; - - // Change database name. - $databaseName = $this->getDriver($connectionName) === 'sqlite' ? database_path($databaseName) : $databaseName; - $separateBy = $this->separateBy($connectionName); - - $this->app['config']["database.connections.$connectionName.$separateBy"] = $databaseName; - } - - /** - * Get the name of the connection that $connectionName should be based on. - * - * @param string $connectionName - * @return string - */ - public function getBaseConnection(string $connectionName): string - { - return ($connectionName !== 'tenant' ? $connectionName : null) // 'tenant' is not a specific connection, it's the default - ?? $this->app['config']['tenancy.database.based_on'] - ?? $this->originalDefaultConnectionName; // tenancy.database.based_on === null => use the default connection - } - - /** - * Get the driver of a database connection. - * - * @param string $connectionName - * @return string|null - */ - public function getDriver(string $connectionName): ?string - { - return $this->app['config']["database.connections.$connectionName.driver"]; + $this->app['config']["database.connections.$connectionName"] = $tenant->database->connection(); } /** * Switch the application's connection. - * - * @param string $connection - * @return void */ public function switchConnection(string $connection) { @@ -146,16 +98,14 @@ class DatabaseManager /** * Check if a tenant can be created. - * - * @param Tenant $tenant - * @return void + * * @throws TenantCannotBeCreatedException * @throws DatabaseManagerNotRegisteredException * @throws TenantDatabaseAlreadyExistsException */ public function ensureTenantCanBeCreated(Tenant $tenant): void { - if ($this->getTenantDatabaseManager($tenant)->databaseExists($database = $tenant->getDatabaseName())) { + if ($tenant->database()->manager()->databaseExists($database = $tenant->database()->getName())) { throw new TenantDatabaseAlreadyExistsException($database); } } @@ -170,50 +120,63 @@ class DatabaseManager */ public function createDatabase(Tenant $tenant, array $afterCreating = []) { - $database = $tenant->getDatabaseName(); - $manager = $this->getTenantDatabaseManager($tenant); + $tenant->database()->makeCredentials(); $afterCreating = array_merge( $afterCreating, - $this->tenancy->event('database.creating', $database, $tenant) + $this->tenancy->event('database.creating', $tenant->database()->getName(), $tenant) ); if ($this->app['config']['tenancy.queue_database_creation'] ?? false) { - $chain = []; - foreach ($afterCreating as $item) { - if (is_string($item) && class_exists($item)) { - $chain[] = new $item($tenant); // Classes are instantiated and given $tenant - } elseif ($item instanceof ShouldQueue) { - $chain[] = $item; - } - } - - QueuedTenantDatabaseCreator::withChain($chain)->dispatch($manager, $database); + $this->createDatabaseAsynchronously($tenant, $afterCreating); } else { - $manager->createDatabase($database); - foreach ($afterCreating as $item) { - if (is_object($item) && ! $item instanceof Closure) { - $item->handle($tenant); - } else { - $item($tenant); - } + $this->createDatabaseSynchronously($tenant, $afterCreating); + } + + $this->tenancy->event('database.created', $tenant->database()->getName(), $tenant); + } + + protected function createDatabaseAsynchronously(Tenant $tenant, array $afterCreating) + { + $chain = []; + foreach ($afterCreating as $item) { + if (is_string($item) && class_exists($item)) { + $chain[] = new $item($tenant); // Classes are instantiated and given $tenant + } elseif ($item instanceof ShouldQueue) { + $chain[] = $item; } } - $this->tenancy->event('database.created', $database, $tenant); + QueuedTenantDatabaseCreator::withChain($chain)->dispatch($tenant->database()->manager(), $tenant->database()); + } + + protected function createDatabaseSynchronously(Tenant $tenant, array $afterCreating) + { + $manager = $tenant->database()->manager(); + $manager->createDatabase($tenant->database()->getName()); + + if ($manager instanceof ManagesDatabaseUsers) { + $manager->createUser($tenant->database()); + } + + foreach ($afterCreating as $item) { + if (is_object($item) && !$item instanceof Closure) { + $item->handle($tenant); + } else { + $item($tenant); + } + } } /** * Delete a tenant's database. - * - * @param Tenant $tenant - * @return void + * * @throws DatabaseManagerNotRegisteredException */ public function deleteDatabase(Tenant $tenant) { - $database = $tenant->getDatabaseName(); - $manager = $this->getTenantDatabaseManager($tenant); + $database = $tenant->database()->getName(); + $manager = $tenant->database()->manager(); $this->tenancy->event('database.deleting', $database, $tenant); @@ -221,50 +184,11 @@ class DatabaseManager QueuedTenantDatabaseDeleter::dispatch($manager, $database); } else { $manager->deleteDatabase($database); + if ($manager instanceof ManagesDatabaseUsers) { + $manager->deleteUser($tenant->database()); + } } $this->tenancy->event('database.deleted', $database, $tenant); } - - /** - * Get the TenantDatabaseManager for a tenant's database connection. - * - * @param Tenant $tenant - * @return TenantDatabaseManager - * @throws DatabaseManagerNotRegisteredException - */ - public function getTenantDatabaseManager(Tenant $tenant): TenantDatabaseManager - { - $driver = $this->getDriver($this->getBaseConnection($connectionName = $tenant->getConnectionName())); - - $databaseManagers = $this->app['config']['tenancy.database_managers']; - - if (! array_key_exists($driver, $databaseManagers)) { - throw new DatabaseManagerNotRegisteredException($driver); - } - - $databaseManager = $this->app[$databaseManagers[$driver]]; - - if ($connectionName !== 'tenant' && $databaseManager instanceof CanSetConnection) { - $databaseManager->setConnection($connectionName); - } - - return $databaseManager; - } - - /** - * What key on the connection config should be used to separate tenants. - * - * @param string $connectionName - * @return string - */ - public function separateBy(string $connectionName): string - { - if ($this->getDriver($this->getBaseConnection($connectionName)) === 'pgsql' - && $this->app['config']['tenancy.database.separate_by'] === 'schema') { - return 'schema'; - } - - return 'database'; - } } diff --git a/src/Jobs/QueuedTenantDatabaseCreator.php b/src/Jobs/QueuedTenantDatabaseCreator.php index bd03fc55..f081c212 100644 --- a/src/Jobs/QueuedTenantDatabaseCreator.php +++ b/src/Jobs/QueuedTenantDatabaseCreator.php @@ -9,7 +9,9 @@ use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Foundation\Bus\Dispatchable; use Illuminate\Queue\InteractsWithQueue; use Illuminate\Queue\SerializesModels; +use Stancl\Tenancy\Contracts\ManagesDatabaseUsers; use Stancl\Tenancy\Contracts\TenantDatabaseManager; +use Stancl\Tenancy\Tenant; class QueuedTenantDatabaseCreator implements ShouldQueue { @@ -18,20 +20,13 @@ class QueuedTenantDatabaseCreator implements ShouldQueue /** @var TenantDatabaseManager */ protected $databaseManager; - /** @var string */ - protected $databaseName; + /** @var Tenant */ + protected $tenant; - /** - * Create a new job instance. - * - * @param TenantDatabaseManager $databaseManager - * @param string $databaseName - * @return void - */ - public function __construct(TenantDatabaseManager $databaseManager, string $databaseName) + public function __construct(TenantDatabaseManager $databaseManager, Tenant $tenant) { $this->databaseManager = $databaseManager; - $this->databaseName = $databaseName; + $this->tenant = $tenant; } /** @@ -42,5 +37,9 @@ class QueuedTenantDatabaseCreator implements ShouldQueue public function handle() { $this->databaseManager->createDatabase($this->databaseName); + + if ($this->databaseManager instanceof ManagesDatabaseUsers) { + $this->databaseManager->createUser($this->tenant->database()); + } } } diff --git a/src/Jobs/QueuedTenantDatabaseDeleter.php b/src/Jobs/QueuedTenantDatabaseDeleter.php index 7d395579..0912755c 100644 --- a/src/Jobs/QueuedTenantDatabaseDeleter.php +++ b/src/Jobs/QueuedTenantDatabaseDeleter.php @@ -9,7 +9,9 @@ use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Foundation\Bus\Dispatchable; use Illuminate\Queue\InteractsWithQueue; use Illuminate\Queue\SerializesModels; +use Stancl\Tenancy\Contracts\ManagesDatabaseUsers; use Stancl\Tenancy\Contracts\TenantDatabaseManager; +use Stancl\Tenancy\Tenant; class QueuedTenantDatabaseDeleter implements ShouldQueue { @@ -18,20 +20,13 @@ class QueuedTenantDatabaseDeleter implements ShouldQueue /** @var TenantDatabaseManager */ protected $databaseManager; - /** @var string */ - protected $databaseName; + /** @var Tenant */ + protected $tenant; - /** - * Create a new job instance. - * - * @param TenantDatabaseManager $databaseManager - * @param string $databaseName - * @return void - */ - public function __construct(TenantDatabaseManager $databaseManager, string $databaseName) + public function __construct(TenantDatabaseManager $databaseManager, Tenant $tenant) { $this->databaseManager = $databaseManager; - $this->databaseName = $databaseName; + $this->tenant = $tenant; } /** @@ -41,6 +36,9 @@ class QueuedTenantDatabaseDeleter implements ShouldQueue */ public function handle() { - $this->databaseManager->deleteDatabase($this->databaseName); + $this->databaseManager->deleteDatabase($this->tenant->database()->getName()); + if ($this->databaseManager instanceof ManagesDatabaseUsers) { + $this->databaseManager->deleteUser($this->tenant->database()); + } } } diff --git a/src/TenancyBootstrappers/DatabaseTenancyBootstrapper.php b/src/TenancyBootstrappers/DatabaseTenancyBootstrapper.php index 8920f44a..bc9cc9b4 100644 --- a/src/TenancyBootstrappers/DatabaseTenancyBootstrapper.php +++ b/src/TenancyBootstrappers/DatabaseTenancyBootstrapper.php @@ -21,8 +21,8 @@ class DatabaseTenancyBootstrapper implements TenancyBootstrapper public function start(Tenant $tenant) { - $database = $tenant->getDatabaseName(); - if (! $this->database->getTenantDatabaseManager($tenant)->databaseExists($database)) { + $database = $tenant->database()->getName(); + if (! $tenant->database()->manager()->databaseExists($database)) { throw new TenantDatabaseDoesNotExistException($database); } diff --git a/src/Tenant.php b/src/Tenant.php index 38ac7261..86fc8688 100644 --- a/src/Tenant.php +++ b/src/Tenant.php @@ -19,6 +19,7 @@ use Stancl\Tenancy\Exceptions\TenantStorageException; /** * @internal Class is subject to breaking changes in minor and patch versions. */ +// todo make this class serializable class Tenant implements ArrayAccess { use Traits\HasArrayAccess, @@ -91,8 +92,7 @@ class Tenant implements ArrayAccess } /** - * DO NOT CALL THIS METHOD FROM USERLAND. Used by storage - * drivers to create persisted instances of Tenant. + * Used by storage drivers to create persisted instances of Tenant. * * @param array $data * @return self @@ -272,23 +272,13 @@ class Tenant implements ArrayAccess } /** - * Get the tenant's database's name. + * Get database config. * - * @return string + * @return DatabaseConfig */ - public function getDatabaseName(): string + public function database(): DatabaseConfig { - return $this->data['_tenancy_db_name'] ?? ($this->config->get('tenancy.database.prefix') . $this->id . $this->config->get('tenancy.database.suffix')); - } - - /** - * Get the tenant's database connection's name. - * - * @return string - */ - public function getConnectionName(): string - { - return $this->data['_tenancy_db_connection'] ?? 'tenant'; + return new DatabaseConfig($this); } /** diff --git a/src/TenantDatabaseManagers/MySQLDatabaseManager.php b/src/TenantDatabaseManagers/MySQLDatabaseManager.php index f6c4ef96..1e6676da 100644 --- a/src/TenantDatabaseManagers/MySQLDatabaseManager.php +++ b/src/TenantDatabaseManagers/MySQLDatabaseManager.php @@ -8,9 +8,10 @@ use Illuminate\Contracts\Config\Repository; use Illuminate\Database\Connection; use Illuminate\Support\Facades\DB; use Stancl\Tenancy\Contracts\Future\CanSetConnection; +use Stancl\Tenancy\Contracts\ManagesDatabaseUsers; use Stancl\Tenancy\Contracts\TenantDatabaseManager; -class MySQLDatabaseManager implements TenantDatabaseManager, CanSetConnection +class MySQLDatabaseManager implements TenantDatabaseManager, CanSetConnection, ManagesDatabaseUsers { /** @var string */ protected $connection; @@ -20,6 +21,11 @@ class MySQLDatabaseManager implements TenantDatabaseManager, CanSetConnection $this->connection = $config->get('tenancy.database_manager_connections.mysql'); } + public function getSeparator(): string + { + return 'database'; + } + protected function database(): Connection { return DB::connection($this->connection); diff --git a/src/TenantDatabaseManagers/PermissionControlledMySQLDatabaseManager.php b/src/TenantDatabaseManagers/PermissionControlledMySQLDatabaseManager.php new file mode 100644 index 00000000..83c05083 --- /dev/null +++ b/src/TenantDatabaseManagers/PermissionControlledMySQLDatabaseManager.php @@ -0,0 +1,47 @@ +getName(); + $username = $databaseConfig->getUsername(); + $hostname = $databaseConfig->connection()['host']; + $password = $databaseConfig->getPassword(); + + $this->database()->statement("CREATE USER `{$username}`@`{$hostname}` IDENTIFIED BY `{$password}`"); + + $grants = implode(', ', static::$grants); + + if ($this->isVersion8()) { // MySQL 8+ + $grantQuery = "GRANT $grants ON `$database`.* TO `$username`@`$hostname`"; + } else { // MySQL 5.7 + $grantQuery = "GRANT $grants ON $database.* TO `$username`@`$hostname` IDENTIFIED BY '$password'"; + } + + $this->database()->statement($grantQuery); + } + + protected function isVersion8(): bool + { + $version = $this->database()->select($this->db->raw('select version()'))[0]->{'version()'}; + + return version_compare($version, '8.0.0') >= 0; + } + + public function deleteUser(DatabaseConfig $databaseConfig): void + { + $this->database()->statement("DROP USER IF EXISTS '{$databaseConfig->username}'"); + } +} \ No newline at end of file diff --git a/src/TenantDatabaseManagers/PostgreSQLDatabaseManager.php b/src/TenantDatabaseManagers/PostgreSQLDatabaseManager.php index fc21668e..b83ae688 100644 --- a/src/TenantDatabaseManagers/PostgreSQLDatabaseManager.php +++ b/src/TenantDatabaseManagers/PostgreSQLDatabaseManager.php @@ -20,6 +20,11 @@ class PostgreSQLDatabaseManager implements TenantDatabaseManager, CanSetConnecti $this->connection = $config->get('tenancy.database_manager_connections.pgsql'); } + public function getSeparator(): string + { + return 'database'; + } + protected function database(): Connection { return DB::connection($this->connection); diff --git a/src/TenantDatabaseManagers/PostgreSQLSchemaManager.php b/src/TenantDatabaseManagers/PostgreSQLSchemaManager.php index a93ed901..14c05cf0 100644 --- a/src/TenantDatabaseManagers/PostgreSQLSchemaManager.php +++ b/src/TenantDatabaseManagers/PostgreSQLSchemaManager.php @@ -20,6 +20,11 @@ class PostgreSQLSchemaManager implements TenantDatabaseManager, CanSetConnection $this->connection = $config->get('tenancy.database_manager_connections.pgsql'); } + public function getSeparator(): string + { + return 'schema'; + } + protected function database(): Connection { return DB::connection($this->connection); diff --git a/src/TenantDatabaseManagers/SQLiteDatabaseManager.php b/src/TenantDatabaseManagers/SQLiteDatabaseManager.php index 5d681ded..95609681 100644 --- a/src/TenantDatabaseManagers/SQLiteDatabaseManager.php +++ b/src/TenantDatabaseManagers/SQLiteDatabaseManager.php @@ -8,6 +8,11 @@ use Stancl\Tenancy\Contracts\TenantDatabaseManager; class SQLiteDatabaseManager implements TenantDatabaseManager { + public function getSeparator(): string + { + return 'database'; + } + public function createDatabase(string $name): bool { try { diff --git a/tests/DatabaseManagerTest.php b/tests/DatabaseManagerTest.php index 9195ef69..9bf91cb3 100644 --- a/tests/DatabaseManagerTest.php +++ b/tests/DatabaseManagerTest.php @@ -32,12 +32,12 @@ class DatabaseManagerTest extends TestCase } /** @test */ - public function the_default_db_is_used_when_based_on_is_null() + public function the_default_db_is_used_when_template_connection_is_null() { $this->assertSame('sqlite', config('database.default')); config([ 'database.connections.sqlite.foo' => 'bar', - 'tenancy.database.based_on' => null, + 'tenancy.database.template_connection' => null, ]); tenancy()->init('test.localhost'); diff --git a/tests/DatabaseSchemaManagerTest.php b/tests/DatabaseSchemaManagerTest.php index 5f9589e0..e2ed64a7 100644 --- a/tests/DatabaseSchemaManagerTest.php +++ b/tests/DatabaseSchemaManagerTest.php @@ -19,9 +19,8 @@ class DatabaseSchemaManagerTest extends TestCase 'database.default' => 'pgsql', 'database.connections.pgsql.database' => 'main', 'database.connections.pgsql.schema' => 'public', - 'tenancy.database.based_on' => null, + 'tenancy.database.template_connection' => null, 'tenancy.database.suffix' => '', - 'tenancy.database.separate_by' => 'schema', 'tenancy.database_managers.pgsql' => \Stancl\Tenancy\TenantDatabaseManagers\PostgreSQLSchemaManager::class, ]); } @@ -41,14 +40,14 @@ class DatabaseSchemaManagerTest extends TestCase } /** @test */ - public function the_default_db_is_used_when_based_on_is_null() + public function the_default_db_is_used_when_template_connection_is_null() { config(['database.default' => 'pgsql']); $this->assertSame('pgsql', config('database.default')); config([ 'database.connections.pgsql.foo' => 'bar', - 'tenancy.database.based_on' => null, + 'tenancy.database.template_connection' => null, ]); tenancy()->init('test.localhost'); @@ -63,7 +62,7 @@ class DatabaseSchemaManagerTest extends TestCase $tenant = tenancy()->create(['schema.localhost']); tenancy()->init('schema.localhost'); - $this->assertSame($tenant->getDatabaseName(), config('database.connections.' . config('database.default') . '.schema')); + $this->assertSame($tenant->database()->getName(), config('database.connections.' . config('database.default') . '.schema')); } /** @test */ diff --git a/tests/DatabaseUsersTest.php b/tests/DatabaseUsersTest.php new file mode 100644 index 00000000..2de11f2e --- /dev/null +++ b/tests/DatabaseUsersTest.php @@ -0,0 +1,24 @@ + $database, ]); - $this->assertSame($database, $tenant->getDatabaseName()); + $this->assertSame($database, $tenant->database()->getName()); } /** @test */ diff --git a/tests/TestCase.php b/tests/TestCase.php index 5d865549..a753e321 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -82,7 +82,7 @@ abstract class TestCase extends \Orchestra\Testbench\TestCase 'database' => database_path('central.sqlite'), ], 'tenancy.database' => [ - 'based_on' => 'sqlite', + 'template_connection' => 'sqlite', 'prefix' => 'tenant', 'suffix' => '.sqlite', ],