mirror of
https://github.com/archtechx/tenancy.git
synced 2026-02-05 01:54:04 +00:00
Merge branch '1.x' into global-ns
This commit is contained in:
commit
3c1f3731d9
9 changed files with 65 additions and 22 deletions
|
|
@ -36,6 +36,8 @@ Open `app/Http/Kernel.php` and make the middleware top priority, so that it gets
|
||||||
```php
|
```php
|
||||||
protected $middlewarePriority = [
|
protected $middlewarePriority = [
|
||||||
\Stancl\Tenancy\Middleware\InitializeTenancy::class,
|
\Stancl\Tenancy\Middleware\InitializeTenancy::class,
|
||||||
|
// ...
|
||||||
|
];
|
||||||
```
|
```
|
||||||
|
|
||||||
When a tenant route is visited, but the tenant can't be identified, an exception is thrown. If you want to change this behavior, to a redirect for example, add this to your `app/Providers/AppServiceProvider.php`'s `boot()` method.
|
When a tenant route is visited, but the tenant can't be identified, an exception is thrown. If you want to change this behavior, to a redirect for example, add this to your `app/Providers/AppServiceProvider.php`'s `boot()` method.
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ interface StorageDriver
|
||||||
public function createTenant(string $domain, string $uuid): array;
|
public function createTenant(string $domain, string $uuid): array;
|
||||||
public function deleteTenant(string $uuid): bool;
|
public function deleteTenant(string $uuid): bool;
|
||||||
public function get(string $uuid, string $key);
|
public function get(string $uuid, string $key);
|
||||||
public function getMany(string $uuid, array $keys);
|
public function getMany(string $uuid, array $keys): array;
|
||||||
public function put(string $uuid, string $key, $value);
|
public function put(string $uuid, string $key, $value);
|
||||||
public function putMany(string $uuid, array $values); // todo better argument name than "values" for kv pairs?
|
public function putMany(string $uuid, array $values): array;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,9 +19,8 @@ class QueuedTenantDatabaseCreator implements ShouldQueue
|
||||||
/**
|
/**
|
||||||
* Create a new job instance.
|
* Create a new job instance.
|
||||||
*
|
*
|
||||||
* @param DatabaseCreator $databaseCreator
|
* @param TenantDatabaseManager $databaseManager
|
||||||
* @param string $databaseName
|
* @param string $databaseName
|
||||||
* @param string $action
|
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function __construct(TenantDatabaseManager $databaseManager, string $databaseName)
|
public function __construct(TenantDatabaseManager $databaseManager, string $databaseName)
|
||||||
|
|
@ -37,6 +36,6 @@ class QueuedTenantDatabaseCreator implements ShouldQueue
|
||||||
*/
|
*/
|
||||||
public function handle()
|
public function handle()
|
||||||
{
|
{
|
||||||
$this->databaseManager->createDatabase($databaseName);
|
$this->databaseManager->createDatabase($this->databaseName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,9 +19,8 @@ class QueuedTenantDatabaseDeleter implements ShouldQueue
|
||||||
/**
|
/**
|
||||||
* Create a new job instance.
|
* Create a new job instance.
|
||||||
*
|
*
|
||||||
* @param DatabaseCreator $databaseCreator
|
* @param TenantDatabaseManager $databaseManager
|
||||||
* @param string $databaseName
|
* @param string $databaseName
|
||||||
* @param string $action
|
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function __construct(TenantDatabaseManager $databaseManager, string $databaseName)
|
public function __construct(TenantDatabaseManager $databaseManager, string $databaseName)
|
||||||
|
|
@ -37,6 +36,6 @@ class QueuedTenantDatabaseDeleter implements ShouldQueue
|
||||||
*/
|
*/
|
||||||
public function handle()
|
public function handle()
|
||||||
{
|
{
|
||||||
$this->databaseManager->deleteDatabase($databaseName);
|
$this->databaseManager->deleteDatabase($this->databaseName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -25,13 +25,7 @@ class InitializeTenancy
|
||||||
try {
|
try {
|
||||||
\tenancy()->init();
|
\tenancy()->init();
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
// Pass the exception to the onFail function if it takes any parameters.
|
($this->onFail)($e);
|
||||||
$callback = $this->onFail;
|
|
||||||
if ((new \ReflectionFunction($callback))->getNumberOfParameters() > 0) {
|
|
||||||
$callback($e);
|
|
||||||
} else {
|
|
||||||
$callback();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return $next($request);
|
return $next($request);
|
||||||
|
|
|
||||||
|
|
@ -71,9 +71,20 @@ class RedisStorageDriver implements StorageDriver
|
||||||
return "tenants:{$hash}";
|
return "tenants:{$hash}";
|
||||||
}, $uuids);
|
}, $uuids);
|
||||||
|
|
||||||
$hashes = $hashes ?: $this->redis->scan(null, 'tenants:*');
|
// Apparently, the PREFIX is applied to all functions except scan()
|
||||||
|
$redis_prefix = $this->redis->getOption($this->redis->client()::OPT_PREFIX);
|
||||||
|
$hashes = $hashes ?: $this->redis->scan(null, $redis_prefix.'tenants:*');
|
||||||
|
|
||||||
|
return array_map(function ($tenant) use ($redis_prefix) {
|
||||||
|
// Left strip $redis_prefix from $tenant
|
||||||
|
if (substr($tenant, 0, strlen($redis_prefix)) == $redis_prefix) {
|
||||||
|
$tenant = substr($tenant, strlen($redis_prefix));
|
||||||
|
}
|
||||||
|
|
||||||
|
<<<<<<< HEAD
|
||||||
return \array_map(function ($tenant) {
|
return \array_map(function ($tenant) {
|
||||||
|
=======
|
||||||
|
>>>>>>> 1.x
|
||||||
return $this->redis->hgetall($tenant);
|
return $this->redis->hgetall($tenant);
|
||||||
}, $hashes);
|
}, $hashes);
|
||||||
}
|
}
|
||||||
|
|
@ -83,7 +94,7 @@ class RedisStorageDriver implements StorageDriver
|
||||||
return $this->redis->hget("tenants:$uuid", $key);
|
return $this->redis->hget("tenants:$uuid", $key);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getMany(string $uuid, array $keys)
|
public function getMany(string $uuid, array $keys): array
|
||||||
{
|
{
|
||||||
return $this->redis->hmget("tenants:$uuid", $keys);
|
return $this->redis->hmget("tenants:$uuid", $keys);
|
||||||
}
|
}
|
||||||
|
|
@ -94,7 +105,7 @@ class RedisStorageDriver implements StorageDriver
|
||||||
return $value;
|
return $value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function putMany(string $uuid, array $values)
|
public function putMany(string $uuid, array $values): array
|
||||||
{
|
{
|
||||||
$this->redis->hmset("tenants:$uuid", $values);
|
$this->redis->hmset("tenants:$uuid", $values);
|
||||||
return $values;
|
return $values;
|
||||||
|
|
|
||||||
|
|
@ -77,7 +77,7 @@ class TenantManager
|
||||||
throw new \Exception("Domain $domain is already occupied by tenant $id.");
|
throw new \Exception("Domain $domain is already occupied by tenant $id.");
|
||||||
}
|
}
|
||||||
|
|
||||||
$tenant = $this->jsonDecodeArrayValues($this->storage->createTenant($domain, \Webpatser\Uuid\Uuid::generate(1, $domain)));
|
$tenant = $this->jsonDecodeArrayValues($this->storage->createTenant($domain, (string) \Webpatser\Uuid\Uuid::generate(1, $domain)));
|
||||||
$this->database->create($this->getDatabaseName($tenant));
|
$this->database->create($this->getDatabaseName($tenant));
|
||||||
|
|
||||||
return $tenant;
|
return $tenant;
|
||||||
|
|
@ -201,7 +201,7 @@ class TenantManager
|
||||||
*/
|
*/
|
||||||
public function all($uuids = [])
|
public function all($uuids = [])
|
||||||
{
|
{
|
||||||
$uuid = (array) $uuids;
|
$uuids = (array) $uuids;
|
||||||
|
|
||||||
return \collect(\array_map(function ($tenant_array) {
|
return \collect(\array_map(function ($tenant_array) {
|
||||||
return $this->jsonDecodeArrayValues($tenant_array);
|
return $this->jsonDecodeArrayValues($tenant_array);
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,22 @@ class TenantDatabaseManagerTest extends TestCase
|
||||||
$this->assertFileNotExists(database_path($db_name));
|
$this->assertFileNotExists(database_path($db_name));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @test */
|
||||||
|
public function sqlite_database_can_be_created_and_deleted_using_queued_commands()
|
||||||
|
{
|
||||||
|
$db_name = 'testdatabase' . $this->randomString(10) . '.sqlite';
|
||||||
|
|
||||||
|
$databaseManagers = config('tenancy.database_managers');
|
||||||
|
$job = new QueuedTenantDatabaseCreator(app($databaseManagers['sqlite']), $db_name);
|
||||||
|
$job->handle();
|
||||||
|
|
||||||
|
$this->assertFileExists(database_path($db_name));
|
||||||
|
|
||||||
|
$job = new QueuedTenantDatabaseDeleter(app($databaseManagers['sqlite']), $db_name);
|
||||||
|
$job->handle();
|
||||||
|
$this->assertFileNotExists(database_path($db_name));
|
||||||
|
}
|
||||||
|
|
||||||
/** @test */
|
/** @test */
|
||||||
public function mysql_database_can_be_created_and_deleted()
|
public function mysql_database_can_be_created_and_deleted()
|
||||||
{
|
{
|
||||||
|
|
@ -38,6 +54,30 @@ class TenantDatabaseManagerTest extends TestCase
|
||||||
$this->assertEmpty(DB::select("SELECT SCHEMA_NAME FROM INFORMATION_SCHEMA.SCHEMATA WHERE SCHEMA_NAME = '$db_name'"));
|
$this->assertEmpty(DB::select("SELECT SCHEMA_NAME FROM INFORMATION_SCHEMA.SCHEMATA WHERE SCHEMA_NAME = '$db_name'"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @test */
|
||||||
|
public function mysql_database_can_be_created_and_deleted_using_queued_commands()
|
||||||
|
{
|
||||||
|
if (! $this->isTravis()) {
|
||||||
|
$this->markTestSkipped('As to not bloat your MySQL instance with test databases, this test is not run by default.');
|
||||||
|
}
|
||||||
|
|
||||||
|
config()->set('database.default', 'mysql');
|
||||||
|
|
||||||
|
$db_name = 'testdatabase' . $this->randomString(10);
|
||||||
|
|
||||||
|
$databaseManagers = config('tenancy.database_managers');
|
||||||
|
$job = new QueuedTenantDatabaseCreator(app($databaseManagers['mysql']), $db_name);
|
||||||
|
$job->handle();
|
||||||
|
|
||||||
|
$this->assertNotEmpty(DB::select("SELECT SCHEMA_NAME FROM INFORMATION_SCHEMA.SCHEMATA WHERE SCHEMA_NAME = '$db_name'"));
|
||||||
|
|
||||||
|
$databaseManagers = config('tenancy.database_managers');
|
||||||
|
$job = new QueuedTenantDatabaseDeleter(app($databaseManagers['mysql']), $db_name);
|
||||||
|
$job->handle();
|
||||||
|
|
||||||
|
$this->assertEmpty(DB::select("SELECT SCHEMA_NAME FROM INFORMATION_SCHEMA.SCHEMATA WHERE SCHEMA_NAME = '$db_name'"));
|
||||||
|
}
|
||||||
|
|
||||||
/** @test */
|
/** @test */
|
||||||
public function database_creation_can_be_queued()
|
public function database_creation_can_be_queued()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -6,8 +6,6 @@ use Stancl\Tenancy\Interfaces\StorageDriver;
|
||||||
|
|
||||||
class TenantStorageTest extends TestCase
|
class TenantStorageTest extends TestCase
|
||||||
{
|
{
|
||||||
// todo find a way to run this for each storage driver (once there are more of them)
|
|
||||||
|
|
||||||
/** @test */
|
/** @test */
|
||||||
public function deleting_a_tenant_works()
|
public function deleting_a_tenant_works()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue