Skip to content

Commit

Permalink
Merge hotfix branch (#834)
Browse files Browse the repository at this point in the history
* try specifying the signature in __construct

* constructor doesn't work since Reflection is used, try specifying getDefaultName() instead

* Fixed: make migration commands compatible

* Fix failing tests

* Fix username generation

* Re-create tmp dir as well if needed

* wip
  • Loading branch information
stancl authored Mar 30, 2022
1 parent 4f19609 commit 349125c
Show file tree
Hide file tree
Showing 10 changed files with 75 additions and 27 deletions.
20 changes: 7 additions & 13 deletions src/Commands/Migrate.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,32 +8,26 @@
use Illuminate\Database\Console\Migrations\MigrateCommand;
use Illuminate\Database\Migrations\Migrator;
use Stancl\Tenancy\Concerns\DealsWithMigrations;
use Stancl\Tenancy\Concerns\ExtendsLaravelCommand;
use Stancl\Tenancy\Concerns\HasATenantsOption;
use Stancl\Tenancy\Events\DatabaseMigrated;
use Stancl\Tenancy\Events\MigratingDatabase;

class Migrate extends MigrateCommand
{
use HasATenantsOption, DealsWithMigrations;
use HasATenantsOption, DealsWithMigrations, ExtendsLaravelCommand;

/**
* The console command description.
*
* @var string
*/
protected $description = 'Run migrations for tenant(s)';

/**
* Create a new command instance.
*
* @param Migrator $migrator
* @param Dispatcher $dispatcher
*/
protected static function getTenantCommandName(): string
{
return 'tenants:migrate';
}

public function __construct(Migrator $migrator, Dispatcher $dispatcher)
{
parent::__construct($migrator, $dispatcher);

$this->setName('tenants:migrate');
$this->specifyParameters();
}

Expand Down
2 changes: 1 addition & 1 deletion src/Commands/MigrateFresh.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ final class MigrateFresh extends Command
public function __construct()
{
parent::__construct();

$this->addOption('--drop-views', null, InputOption::VALUE_NONE, 'Drop views along with tenant tables.', null);

$this->setName('tenants:migrate-fresh');
Expand Down
11 changes: 8 additions & 3 deletions src/Commands/Rollback.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,19 @@
use Illuminate\Database\Console\Migrations\RollbackCommand;
use Illuminate\Database\Migrations\Migrator;
use Stancl\Tenancy\Concerns\DealsWithMigrations;
use Stancl\Tenancy\Concerns\ExtendsLaravelCommand;
use Stancl\Tenancy\Concerns\HasATenantsOption;
use Stancl\Tenancy\Events\DatabaseRolledBack;
use Stancl\Tenancy\Events\RollingBackDatabase;

class Rollback extends RollbackCommand
{
use HasATenantsOption, DealsWithMigrations;
use HasATenantsOption, DealsWithMigrations, ExtendsLaravelCommand;

protected static function getTenantCommandName(): string
{
return 'tenants:rollback';
}

/**
* The console command description.
Expand All @@ -31,8 +37,7 @@ public function __construct(Migrator $migrator)
{
parent::__construct($migrator);

$this->setName('tenants:rollback');
$this->specifyParameters();
$this->specifyTenantSignature();
}

/**
Expand Down
23 changes: 23 additions & 0 deletions src/Concerns/ExtendsLaravelCommand.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?php

namespace Stancl\Tenancy\Concerns;

trait ExtendsLaravelCommand
{
protected function specifyTenantSignature(): void
{
$this->specifyParameters();
}

public function getName(): ?string
{
return static::getTenantCommandName();
}

public static function getDefaultName(): ?string
{
return static::getTenantCommandName();
}

abstract protected static function getTenantCommandName(): string;
}
10 changes: 9 additions & 1 deletion src/Database/DatabaseManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,12 @@
use Illuminate\Config\Repository;
use Illuminate\Contracts\Foundation\Application;
use Illuminate\Database\DatabaseManager as BaseDatabaseManager;
use Stancl\Tenancy\Contracts\ManagesDatabaseUsers;
use Stancl\Tenancy\Contracts\TenantCannotBeCreatedException;
use Stancl\Tenancy\Contracts\TenantWithDatabase;
use Stancl\Tenancy\Exceptions\DatabaseManagerNotRegisteredException;
use Stancl\Tenancy\Exceptions\TenantDatabaseAlreadyExistsException;
use Stancl\Tenancy\Exceptions\TenantDatabaseUserAlreadyExistsException;

/**
* @internal Class is subject to breaking changes in minor and patch versions.
Expand Down Expand Up @@ -90,8 +92,14 @@ public function purgeTenantConnection()
*/
public function ensureTenantCanBeCreated(TenantWithDatabase $tenant): void
{
if ($tenant->database()->manager()->databaseExists($database = $tenant->database()->getName())) {
$manager = $tenant->database()->manager();

if ($manager->databaseExists($database = $tenant->database()->getName())) {
throw new TenantDatabaseAlreadyExistsException($database);
}

if ($manager instanceof ManagesDatabaseUsers && $manager->userExists($username = $tenant->database()->getUsername())) {
throw new TenantDatabaseUserAlreadyExistsException($username);
}
}
}
2 changes: 1 addition & 1 deletion src/Jobs/CreateDatabase.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ public function handle(DatabaseManager $databaseManager)
return false;
}

$databaseManager->ensureTenantCanBeCreated($this->tenant);
$this->tenant->database()->makeCredentials();
$databaseManager->ensureTenantCanBeCreated($this->tenant);
$this->tenant->database()->manager()->createDatabase($this->tenant);

event(new DatabaseCreated($this->tenant));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
use Stancl\Tenancy\Concerns\CreatesDatabaseUsers;
use Stancl\Tenancy\Contracts\ManagesDatabaseUsers;
use Stancl\Tenancy\DatabaseConfig;
use Stancl\Tenancy\Exceptions\TenantDatabaseUserAlreadyExistsException;

class PermissionControlledMySQLDatabaseManager extends MySQLDatabaseManager implements ManagesDatabaseUsers
{
Expand All @@ -26,10 +25,6 @@ public function createUser(DatabaseConfig $databaseConfig): bool
$hostname = $databaseConfig->connection()['host'];
$password = $databaseConfig->getPassword();

if ($this->userExists($username)) {
throw new TenantDatabaseUserAlreadyExistsException($username);
}

$this->database()->statement("CREATE USER `{$username}`@`%` IDENTIFIED BY '{$password}'");

$grants = implode(', ', static::$grants);
Expand Down
9 changes: 7 additions & 2 deletions tests/DatabaseUsersTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
use Stancl\JobPipeline\JobPipeline;
use Stancl\Tenancy\Bootstrappers\DatabaseTenancyBootstrapper;
use Stancl\Tenancy\Contracts\ManagesDatabaseUsers;
use Stancl\Tenancy\Events\DatabaseCreated;
use Stancl\Tenancy\Events\TenancyInitialized;
use Stancl\Tenancy\Events\TenantCreated;
use Stancl\Tenancy\Exceptions\TenantDatabaseUserAlreadyExistsException;
Expand Down Expand Up @@ -67,14 +68,18 @@ public function a_tenants_database_cannot_be_created_when_the_user_already_exist
$this->assertTrue($manager->databaseExists($tenant->database()->getName()));

$this->expectException(TenantDatabaseUserAlreadyExistsException::class);
Event::fake([DatabaseCreated::class]);

$tenant2 = Tenant::create([
'tenancy_db_username' => $username,
]);

/** @var ManagesDatabaseUsers $manager */
$manager = $tenant2->database()->manager();
$manager2 = $tenant2->database()->manager();

// database was not created because of DB transaction
$this->assertFalse($manager->databaseExists($tenant2->database()->getName()));
$this->assertFalse($manager2->databaseExists($tenant2->database()->getName()));
Event::assertNotDispatched(DatabaseCreated::class);
}

/** @test */
Expand Down
Empty file removed tests/Etc/tmp/queuetest.json
Empty file.
20 changes: 19 additions & 1 deletion tests/QueueTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace Stancl\Tenancy\Tests;

use Closure;
use Exception;
use Illuminate\Support\Str;
use Illuminate\Bus\Queueable;
Expand All @@ -24,6 +25,7 @@
use Illuminate\Queue\Events\JobProcessing;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use PDO;
use Stancl\Tenancy\Events\TenancyInitialized;
use Stancl\Tenancy\Listeners\BootstrapTenancy;
use Stancl\Tenancy\Listeners\RevertToCentralContext;
Expand Down Expand Up @@ -52,14 +54,30 @@ public function setUp(): void
Event::listen(TenancyInitialized::class, BootstrapTenancy::class);
Event::listen(TenancyEnded::class, RevertToCentralContext::class);

$this->valuestore = Valuestore::make(__DIR__ . '/Etc/tmp/queuetest.json')->flush();
$this->createValueStore();
}

public function tearDown(): void
{
$this->valuestore->flush();
}

protected function createValueStore(): void
{
$valueStorePath = __DIR__ . '/Etc/tmp/queuetest.json';

if (! file_exists($valueStorePath)) {
// The directory sometimes goes missing as well when the file is deleted in git
if (! is_dir(__DIR__ . '/Etc/tmp')) {
mkdir(__DIR__ . '/Etc/tmp');
}

file_put_contents($valueStorePath, '');
}

$this->valuestore = Valuestore::make($valueStorePath)->flush();
}

protected function withFailedJobs()
{
Schema::connection('central')->create('failed_jobs', function (Blueprint $table) {
Expand Down

0 comments on commit 349125c

Please sign in to comment.