mirror of
https://github.com/archtechx/tenancy.git
synced 2026-02-05 04:34:03 +00:00
POC with no polish (#376)
Signed-off-by: michael lundbøl <michael.lundboel@gmail.com> Co-authored-by: michael lundbøl <michael.lundboel@gmail.com>
This commit is contained in:
parent
b51c7a399c
commit
37242279fe
12 changed files with 225 additions and 34 deletions
|
|
@ -108,8 +108,6 @@ return [
|
||||||
*/
|
*/
|
||||||
'prefix' => 'tenant',
|
'prefix' => 'tenant',
|
||||||
'suffix' => '',
|
'suffix' => '',
|
||||||
|
|
||||||
'separate_by' => 'database', // database or schema (only supported by pgsql)
|
|
||||||
],
|
],
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
11
src/Contracts/ManagesDatabaseUsers.php
Normal file
11
src/Contracts/ManagesDatabaseUsers.php
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Stancl\Tenancy\Contracts;
|
||||||
|
|
||||||
|
use Stancl\Tenancy\Contracts\Future\CanSetConnection;
|
||||||
|
use Stancl\Tenancy\Tenant;
|
||||||
|
|
||||||
|
interface ManagesDatabaseUsers extends CanSetConnection
|
||||||
|
{
|
||||||
|
public function createDatabaseUser(string $databaseName, Tenant $tenant): void;
|
||||||
|
}
|
||||||
|
|
@ -4,15 +4,18 @@ declare(strict_types=1);
|
||||||
|
|
||||||
namespace Stancl\Tenancy\Contracts;
|
namespace Stancl\Tenancy\Contracts;
|
||||||
|
|
||||||
|
use Stancl\Tenancy\Tenant;
|
||||||
|
|
||||||
interface TenantDatabaseManager
|
interface TenantDatabaseManager
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Create a database.
|
* Create a database.
|
||||||
*
|
*
|
||||||
* @param string $name Name of the database.
|
* @param string $name Name of the database.
|
||||||
|
* @param Tenant $tenant
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
public function createDatabase(string $name): bool;
|
public function createDatabase(string $name, Tenant $tenant): bool;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delete a database.
|
* Delete a database.
|
||||||
|
|
@ -29,4 +32,14 @@ interface TenantDatabaseManager
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
public function databaseExists(string $name): bool;
|
public function databaseExists(string $name): bool;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Override the base connection
|
||||||
|
*
|
||||||
|
* @param Tenant $tenant
|
||||||
|
* @param array $baseConfiguration
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function createDatabaseConnection(Tenant $tenant, array $baseConfiguration): array;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ use Illuminate\Contracts\Queue\ShouldQueue;
|
||||||
use Illuminate\Database\DatabaseManager as BaseDatabaseManager;
|
use Illuminate\Database\DatabaseManager as BaseDatabaseManager;
|
||||||
use Illuminate\Foundation\Application;
|
use Illuminate\Foundation\Application;
|
||||||
use Stancl\Tenancy\Contracts\Future\CanSetConnection;
|
use Stancl\Tenancy\Contracts\Future\CanSetConnection;
|
||||||
|
use Stancl\Tenancy\Contracts\ManagesDatabaseUsers;
|
||||||
use Stancl\Tenancy\Contracts\TenantCannotBeCreatedException;
|
use Stancl\Tenancy\Contracts\TenantCannotBeCreatedException;
|
||||||
use Stancl\Tenancy\Contracts\TenantDatabaseManager;
|
use Stancl\Tenancy\Contracts\TenantDatabaseManager;
|
||||||
use Stancl\Tenancy\Exceptions\DatabaseManagerNotRegisteredException;
|
use Stancl\Tenancy\Exceptions\DatabaseManagerNotRegisteredException;
|
||||||
|
|
@ -58,7 +59,7 @@ class DatabaseManager
|
||||||
*/
|
*/
|
||||||
public function connect(Tenant $tenant)
|
public function connect(Tenant $tenant)
|
||||||
{
|
{
|
||||||
$this->createTenantConnection($tenant->getDatabaseName(), $tenant->getConnectionName());
|
$this->createTenantConnection($tenant);
|
||||||
$this->setDefaultConnection($tenant->getConnectionName());
|
$this->setDefaultConnection($tenant->getConnectionName());
|
||||||
$this->switchConnection($tenant->getConnectionName());
|
$this->switchConnection($tenant->getConnectionName());
|
||||||
}
|
}
|
||||||
|
|
@ -90,21 +91,21 @@ class DatabaseManager
|
||||||
/**
|
/**
|
||||||
* Create the tenant database connection.
|
* Create the tenant database connection.
|
||||||
*
|
*
|
||||||
* @param string $databaseName
|
* @param Tenant $tenant
|
||||||
* @param string $connectionName
|
|
||||||
* @return void
|
* @return void
|
||||||
|
* @throws DatabaseManagerNotRegisteredException
|
||||||
*/
|
*/
|
||||||
public function createTenantConnection($databaseName, $connectionName)
|
public function createTenantConnection(Tenant $tenant)
|
||||||
{
|
{
|
||||||
// Create the database connection.
|
$configuration = $this->getTenantDatabaseManager($tenant)
|
||||||
$based_on = $this->getBaseConnection($connectionName);
|
->createDatabaseConnection(
|
||||||
$this->app['config']["database.connections.$connectionName"] = $this->app['config']['database.connections.' . $based_on];
|
$tenant,
|
||||||
|
$this->getBaseConnectionConfiguration($tenant)
|
||||||
|
);
|
||||||
|
|
||||||
// Change database name.
|
$connectionName = $tenant->getConnectionName();
|
||||||
$databaseName = $this->getDriver($connectionName) === 'sqlite' ? database_path($databaseName) : $databaseName;
|
|
||||||
$separateBy = $this->separateBy($connectionName);
|
|
||||||
|
|
||||||
$this->app['config']["database.connections.$connectionName.$separateBy"] = $databaseName;
|
$this->app['config']->set("database.connections.{$connectionName}", $configuration);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -188,9 +189,9 @@ class DatabaseManager
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QueuedTenantDatabaseCreator::withChain($chain)->dispatch($manager, $database);
|
QueuedTenantDatabaseCreator::withChain($chain)->dispatch($manager, $database, $tenant);
|
||||||
} else {
|
} else {
|
||||||
$manager->createDatabase($database);
|
$manager->createDatabase($database, $tenant);
|
||||||
foreach ($afterCreating as $item) {
|
foreach ($afterCreating as $item) {
|
||||||
if (is_object($item) && ! $item instanceof Closure) {
|
if (is_object($item) && ! $item instanceof Closure) {
|
||||||
$item->handle($tenant);
|
$item->handle($tenant);
|
||||||
|
|
@ -253,18 +254,15 @@ class DatabaseManager
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* What key on the connection config should be used to separate tenants.
|
* Get the connection base configuration for a tenant
|
||||||
*
|
*
|
||||||
* @param string $connectionName
|
* @param Tenant $tenant
|
||||||
* @return string
|
* @return array
|
||||||
*/
|
*/
|
||||||
public function separateBy(string $connectionName): string
|
protected function getBaseConnectionConfiguration(Tenant $tenant): array
|
||||||
{
|
{
|
||||||
if ($this->getDriver($this->getBaseConnection($connectionName)) === 'pgsql'
|
$basedOn = $this->getBaseConnection($tenant->getConnectionName());
|
||||||
&& $this->app['config']['tenancy.database.separate_by'] === 'schema') {
|
|
||||||
return 'schema';
|
|
||||||
}
|
|
||||||
|
|
||||||
return 'database';
|
return $this->app['config']->get("database.connections.{$basedOn}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ use Illuminate\Foundation\Bus\Dispatchable;
|
||||||
use Illuminate\Queue\InteractsWithQueue;
|
use Illuminate\Queue\InteractsWithQueue;
|
||||||
use Illuminate\Queue\SerializesModels;
|
use Illuminate\Queue\SerializesModels;
|
||||||
use Stancl\Tenancy\Contracts\TenantDatabaseManager;
|
use Stancl\Tenancy\Contracts\TenantDatabaseManager;
|
||||||
|
use Stancl\Tenancy\Tenant;
|
||||||
|
|
||||||
class QueuedTenantDatabaseCreator implements ShouldQueue
|
class QueuedTenantDatabaseCreator implements ShouldQueue
|
||||||
{
|
{
|
||||||
|
|
@ -21,17 +22,21 @@ class QueuedTenantDatabaseCreator implements ShouldQueue
|
||||||
/** @var string */
|
/** @var string */
|
||||||
protected $databaseName;
|
protected $databaseName;
|
||||||
|
|
||||||
|
/** @var Tenant */
|
||||||
|
public $tenant;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new job instance.
|
* Create a new job instance.
|
||||||
*
|
*
|
||||||
* @param TenantDatabaseManager $databaseManager
|
* @param TenantDatabaseManager $databaseManager
|
||||||
* @param string $databaseName
|
* @param string $databaseName
|
||||||
* @return void
|
* @param Tenant $tenant
|
||||||
*/
|
*/
|
||||||
public function __construct(TenantDatabaseManager $databaseManager, string $databaseName)
|
public function __construct(TenantDatabaseManager $databaseManager, string $databaseName, Tenant $tenant)
|
||||||
{
|
{
|
||||||
$this->databaseManager = $databaseManager;
|
$this->databaseManager = $databaseManager;
|
||||||
$this->databaseName = $databaseName;
|
$this->databaseName = $databaseName;
|
||||||
|
$this->tenant = $tenant;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -41,6 +46,6 @@ class QueuedTenantDatabaseCreator implements ShouldQueue
|
||||||
*/
|
*/
|
||||||
public function handle()
|
public function handle()
|
||||||
{
|
{
|
||||||
$this->databaseManager->createDatabase($this->databaseName);
|
$this->databaseManager->createDatabase($this->databaseName, $this->tenant);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@ use Stancl\Tenancy\Contracts\StorageDriver;
|
||||||
use Stancl\Tenancy\Contracts\UniqueIdentifierGenerator;
|
use Stancl\Tenancy\Contracts\UniqueIdentifierGenerator;
|
||||||
use Stancl\Tenancy\Exceptions\NotImplementedException;
|
use Stancl\Tenancy\Exceptions\NotImplementedException;
|
||||||
use Stancl\Tenancy\Exceptions\TenantStorageException;
|
use Stancl\Tenancy\Exceptions\TenantStorageException;
|
||||||
|
use Stancl\Tenancy\Traits\ProvidesDatabaseUser;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @internal Class is subject to breaking changes in minor and patch versions.
|
* @internal Class is subject to breaking changes in minor and patch versions.
|
||||||
|
|
@ -22,7 +23,8 @@ use Stancl\Tenancy\Exceptions\TenantStorageException;
|
||||||
class Tenant implements ArrayAccess
|
class Tenant implements ArrayAccess
|
||||||
{
|
{
|
||||||
use Traits\HasArrayAccess,
|
use Traits\HasArrayAccess,
|
||||||
ForwardsCalls;
|
ForwardsCalls,
|
||||||
|
ProvidesDatabaseUser;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tenant data. A "cache" of tenant storage.
|
* Tenant data. A "cache" of tenant storage.
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ use Illuminate\Database\Connection;
|
||||||
use Illuminate\Support\Facades\DB;
|
use Illuminate\Support\Facades\DB;
|
||||||
use Stancl\Tenancy\Contracts\Future\CanSetConnection;
|
use Stancl\Tenancy\Contracts\Future\CanSetConnection;
|
||||||
use Stancl\Tenancy\Contracts\TenantDatabaseManager;
|
use Stancl\Tenancy\Contracts\TenantDatabaseManager;
|
||||||
|
use Stancl\Tenancy\Tenant;
|
||||||
|
|
||||||
class MySQLDatabaseManager implements TenantDatabaseManager, CanSetConnection
|
class MySQLDatabaseManager implements TenantDatabaseManager, CanSetConnection
|
||||||
{
|
{
|
||||||
|
|
@ -30,7 +31,7 @@ class MySQLDatabaseManager implements TenantDatabaseManager, CanSetConnection
|
||||||
$this->connection = $connection;
|
$this->connection = $connection;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function createDatabase(string $name): bool
|
public function createDatabase(string $name, Tenant $tenant): bool
|
||||||
{
|
{
|
||||||
$charset = $this->database()->getConfig('charset');
|
$charset = $this->database()->getConfig('charset');
|
||||||
$collation = $this->database()->getConfig('collation');
|
$collation = $this->database()->getConfig('collation');
|
||||||
|
|
@ -47,4 +48,14 @@ class MySQLDatabaseManager implements TenantDatabaseManager, CanSetConnection
|
||||||
{
|
{
|
||||||
return (bool) $this->database()->select("SELECT SCHEMA_NAME FROM INFORMATION_SCHEMA.SCHEMATA WHERE SCHEMA_NAME = '$name'");
|
return (bool) $this->database()->select("SELECT SCHEMA_NAME FROM INFORMATION_SCHEMA.SCHEMATA WHERE SCHEMA_NAME = '$name'");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
public function createDatabaseConnection(Tenant $tenant, array $baseConfiguration): array
|
||||||
|
{
|
||||||
|
return array_replace_recursive($baseConfiguration, [
|
||||||
|
'database' => $tenant->getDatabaseName(),
|
||||||
|
]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,64 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Stancl\Tenancy\TenantDatabaseManagers;
|
||||||
|
|
||||||
|
use Illuminate\Contracts\Config\Repository;
|
||||||
|
use Illuminate\Support\Str;
|
||||||
|
use Stancl\Tenancy\Contracts\DatabaseUserGenerator;
|
||||||
|
use Stancl\Tenancy\Contracts\ManagesDatabaseUsers;
|
||||||
|
use Stancl\Tenancy\Tenant;
|
||||||
|
|
||||||
|
class PermissionControlledMySQLDatabaseManager extends MySQLDatabaseManager implements ManagesDatabaseUsers
|
||||||
|
{
|
||||||
|
public function createDatabase(string $name, Tenant $tenant): bool
|
||||||
|
{
|
||||||
|
parent::createDatabase($name, $tenant);
|
||||||
|
|
||||||
|
$this->createDatabaseUser($name, $tenant);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function createDatabaseConnection(Tenant $tenant, array $baseConfiguration): array
|
||||||
|
{
|
||||||
|
return array_replace_recursive(
|
||||||
|
parent::createDatabaseConnection($tenant, $baseConfiguration),
|
||||||
|
array_filter([
|
||||||
|
'host' => $tenant->getDatabaseHost(),
|
||||||
|
'username' => $tenant->getDatabaseUsername(),
|
||||||
|
'password' => $tenant->getDatabasePassword(),
|
||||||
|
'port' => $tenant->getDatabasePort(),
|
||||||
|
'url' => $tenant->getDatabaseUrl()
|
||||||
|
])
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function createDatabaseUser(string $databaseName, Tenant $tenant): void
|
||||||
|
{
|
||||||
|
$username = $tenant->generateDatabaseUsername();
|
||||||
|
$password = $tenant->generateDatabasePassword();
|
||||||
|
$appHost = $tenant->getDatabaseHost() ?? $this->getBaseConfigurationFor('host');
|
||||||
|
|
||||||
|
$grants = implode(', ', $tenant->getDatabaseGrants());
|
||||||
|
|
||||||
|
$this->database()->statement(
|
||||||
|
"CREATE USER '$username'@'$appHost' IDENTIFIED BY '$password"
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->database()->statement(
|
||||||
|
"GRANT $grants ON $databaseName.* TO '$username'@'$appHost' IDENTIFIED BY '$password'"
|
||||||
|
);
|
||||||
|
|
||||||
|
$tenant->withData([
|
||||||
|
'_tenancy_db_username' => $username,
|
||||||
|
'_tenancy_db_password' => $password,
|
||||||
|
'_tenancy_db_host' => $appHost,
|
||||||
|
'_tenancy_db_link' => $tenant->getDatabaseLink()
|
||||||
|
])->save();
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getBaseConfigurationFor(string $key)
|
||||||
|
{
|
||||||
|
return $this->database()->getConfig($key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -9,6 +9,7 @@ use Illuminate\Database\Connection;
|
||||||
use Illuminate\Support\Facades\DB;
|
use Illuminate\Support\Facades\DB;
|
||||||
use Stancl\Tenancy\Contracts\Future\CanSetConnection;
|
use Stancl\Tenancy\Contracts\Future\CanSetConnection;
|
||||||
use Stancl\Tenancy\Contracts\TenantDatabaseManager;
|
use Stancl\Tenancy\Contracts\TenantDatabaseManager;
|
||||||
|
use Stancl\Tenancy\Tenant;
|
||||||
|
|
||||||
class PostgreSQLDatabaseManager implements TenantDatabaseManager, CanSetConnection
|
class PostgreSQLDatabaseManager implements TenantDatabaseManager, CanSetConnection
|
||||||
{
|
{
|
||||||
|
|
@ -30,7 +31,7 @@ class PostgreSQLDatabaseManager implements TenantDatabaseManager, CanSetConnecti
|
||||||
$this->connection = $connection;
|
$this->connection = $connection;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function createDatabase(string $name): bool
|
public function createDatabase(string $name, Tenant $tenant): bool
|
||||||
{
|
{
|
||||||
return $this->database()->statement("CREATE DATABASE \"$name\" WITH TEMPLATE=template0");
|
return $this->database()->statement("CREATE DATABASE \"$name\" WITH TEMPLATE=template0");
|
||||||
}
|
}
|
||||||
|
|
@ -44,4 +45,18 @@ class PostgreSQLDatabaseManager implements TenantDatabaseManager, CanSetConnecti
|
||||||
{
|
{
|
||||||
return (bool) $this->database()->select("SELECT datname FROM pg_database WHERE datname = '$name'");
|
return (bool) $this->database()->select("SELECT datname FROM pg_database WHERE datname = '$name'");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
public function createDatabaseConnection(Tenant $tenant, array $baseConfiguration): array
|
||||||
|
{
|
||||||
|
if ('pgsql' !== $baseConfiguration['driver']) {
|
||||||
|
throw new \Exception('Mismatching driver for tenant');
|
||||||
|
}
|
||||||
|
|
||||||
|
return array_replace_recursive($baseConfiguration, [
|
||||||
|
'database' => $tenant->getDatabaseName()
|
||||||
|
]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ use Illuminate\Database\Connection;
|
||||||
use Illuminate\Support\Facades\DB;
|
use Illuminate\Support\Facades\DB;
|
||||||
use Stancl\Tenancy\Contracts\Future\CanSetConnection;
|
use Stancl\Tenancy\Contracts\Future\CanSetConnection;
|
||||||
use Stancl\Tenancy\Contracts\TenantDatabaseManager;
|
use Stancl\Tenancy\Contracts\TenantDatabaseManager;
|
||||||
|
use Stancl\Tenancy\Tenant;
|
||||||
|
|
||||||
class PostgreSQLSchemaManager implements TenantDatabaseManager, CanSetConnection
|
class PostgreSQLSchemaManager implements TenantDatabaseManager, CanSetConnection
|
||||||
{
|
{
|
||||||
|
|
@ -30,7 +31,7 @@ class PostgreSQLSchemaManager implements TenantDatabaseManager, CanSetConnection
|
||||||
$this->connection = $connection;
|
$this->connection = $connection;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function createDatabase(string $name): bool
|
public function createDatabase(string $name, Tenant $tenant): bool
|
||||||
{
|
{
|
||||||
return $this->database()->statement("CREATE SCHEMA \"$name\"");
|
return $this->database()->statement("CREATE SCHEMA \"$name\"");
|
||||||
}
|
}
|
||||||
|
|
@ -44,4 +45,15 @@ class PostgreSQLSchemaManager implements TenantDatabaseManager, CanSetConnection
|
||||||
{
|
{
|
||||||
return (bool) $this->database()->select("SELECT schema_name FROM information_schema.schemata WHERE schema_name = '$name'");
|
return (bool) $this->database()->select("SELECT schema_name FROM information_schema.schemata WHERE schema_name = '$name'");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function createDatabaseConnection(Tenant $tenant, array $baseConfiguration): array
|
||||||
|
{
|
||||||
|
if ('pgsql' !== $baseConfiguration['driver']) {
|
||||||
|
throw new \Exception('Mismatching driver for tenant');
|
||||||
|
}
|
||||||
|
|
||||||
|
return array_replace_recursive($baseConfiguration, [
|
||||||
|
'schema' => $tenant->getDatabaseName()
|
||||||
|
]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,10 +5,11 @@ declare(strict_types=1);
|
||||||
namespace Stancl\Tenancy\TenantDatabaseManagers;
|
namespace Stancl\Tenancy\TenantDatabaseManagers;
|
||||||
|
|
||||||
use Stancl\Tenancy\Contracts\TenantDatabaseManager;
|
use Stancl\Tenancy\Contracts\TenantDatabaseManager;
|
||||||
|
use Stancl\Tenancy\Tenant;
|
||||||
|
|
||||||
class SQLiteDatabaseManager implements TenantDatabaseManager
|
class SQLiteDatabaseManager implements TenantDatabaseManager
|
||||||
{
|
{
|
||||||
public function createDatabase(string $name): bool
|
public function createDatabase(string $name, Tenant $tenant): bool
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
return fclose(fopen(database_path($name), 'w'));
|
return fclose(fopen(database_path($name), 'w'));
|
||||||
|
|
@ -30,4 +31,11 @@ class SQLiteDatabaseManager implements TenantDatabaseManager
|
||||||
{
|
{
|
||||||
return file_exists(database_path($name));
|
return file_exists(database_path($name));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function createDatabaseConnection(Tenant $tenant, array $baseConfiguration): array
|
||||||
|
{
|
||||||
|
return array_replace_recursive($baseConfiguration, [
|
||||||
|
'database' => database_path($tenant->getDatabaseName())
|
||||||
|
]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
54
src/Traits/ProvidesDatabaseUser.php
Normal file
54
src/Traits/ProvidesDatabaseUser.php
Normal file
|
|
@ -0,0 +1,54 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Stancl\Tenancy\Traits;
|
||||||
|
|
||||||
|
use Illuminate\Support\Facades\Hash;
|
||||||
|
use Illuminate\Support\Str;
|
||||||
|
|
||||||
|
trait ProvidesDatabaseUser
|
||||||
|
{
|
||||||
|
public function getDatabaseHost(): ?string
|
||||||
|
{
|
||||||
|
return $this->data['_tenancy_db_host'];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getDatabaseUrl(): ?string
|
||||||
|
{
|
||||||
|
return $this->data['_tenancy_db_url'];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getDatabaseUsername(): string
|
||||||
|
{
|
||||||
|
return $this->data['_tenancy_db_username'];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getDatabasePassword(): string
|
||||||
|
{
|
||||||
|
return $this->data['_tenancy_db_password'];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getDatabasePort(): ?string
|
||||||
|
{
|
||||||
|
return $this->data['_tenancy_db_port'] ?? null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getDatabaseGrants(): array
|
||||||
|
{
|
||||||
|
return $this->data['_tenancy_db_grants'] ?? $this->config['tenancy.database.grants'];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function generateDatabaseUsername(): string
|
||||||
|
{
|
||||||
|
return Str::random(16);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function generateDatabasePassword(): string
|
||||||
|
{
|
||||||
|
return Hash::make(Str::random(16));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getDatabaseLink(): ?string
|
||||||
|
{
|
||||||
|
return $this->data['_tenancy_db_link'] ?? null;
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue