mirror of
https://github.com/archtechx/tenancy.git
synced 2025-12-12 19:04:02 +00:00
Tenant DB manager database() -> connection()
This commit is contained in:
parent
f3e01c1581
commit
0fc105487b
13 changed files with 60 additions and 60 deletions
|
|
@ -30,7 +30,7 @@ trait ManagesPostgresUsers
|
|||
$createUser = ! $this->userExists($username);
|
||||
|
||||
if ($createUser) {
|
||||
$this->database()->statement("CREATE USER \"{$username}\" LOGIN PASSWORD '{$password}'");
|
||||
$this->connection()->statement("CREATE USER \"{$username}\" LOGIN PASSWORD '{$password}'");
|
||||
}
|
||||
|
||||
$this->grantPermissions($databaseConfig);
|
||||
|
|
@ -46,38 +46,38 @@ trait ManagesPostgresUsers
|
|||
$username = $databaseConfig->getUsername();
|
||||
|
||||
// Tenant host connection config
|
||||
$connectionName = $this->database()->getConfig('name');
|
||||
$centralDatabase = $this->database()->getConfig('database');
|
||||
$connectionName = $this->connection()->getConfig('name');
|
||||
$centralDatabase = $this->connection()->getConfig('database');
|
||||
|
||||
// Set the DB/schema name to the tenant DB/schema name
|
||||
config()->set(
|
||||
"database.connections.{$connectionName}",
|
||||
$this->makeConnectionConfig($this->database()->getConfig(), $databaseConfig->getName()),
|
||||
$this->makeConnectionConfig($this->connection()->getConfig(), $databaseConfig->getName()),
|
||||
);
|
||||
|
||||
// Connect to the tenant DB/schema
|
||||
$this->database()->reconnect();
|
||||
$this->connection()->reconnect();
|
||||
|
||||
// Delete all database objects owned by the user (privileges, tables, views, etc.)
|
||||
// Postgres users cannot be deleted unless we delete all objects owned by it first
|
||||
$this->database()->statement("DROP OWNED BY \"{$username}\"");
|
||||
$this->connection()->statement("DROP OWNED BY \"{$username}\"");
|
||||
|
||||
// Delete the user
|
||||
$userDeleted = $this->database()->statement("DROP USER \"{$username}\"");
|
||||
$userDeleted = $this->connection()->statement("DROP USER \"{$username}\"");
|
||||
|
||||
config()->set(
|
||||
"database.connections.{$connectionName}",
|
||||
$this->makeConnectionConfig($this->database()->getConfig(), $centralDatabase),
|
||||
$this->makeConnectionConfig($this->connection()->getConfig(), $centralDatabase),
|
||||
);
|
||||
|
||||
// Reconnect to the central database
|
||||
$this->database()->reconnect();
|
||||
$this->connection()->reconnect();
|
||||
|
||||
return $userDeleted;
|
||||
}
|
||||
|
||||
public function userExists(string $username): bool
|
||||
{
|
||||
return (bool) $this->database()->selectOne("SELECT usename FROM pg_user WHERE usename = '{$username}'");
|
||||
return (bool) $this->connection()->selectOne("SELECT usename FROM pg_user WHERE usename = '{$username}'");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ use Stancl\Tenancy\Database\Exceptions\NoConnectionSetException;
|
|||
interface StatefulTenantDatabaseManager extends TenantDatabaseManager
|
||||
{
|
||||
/** Get the DB connection used by the tenant database manager. */
|
||||
public function database(): Connection; // todo@dbRefactor rename to connection()
|
||||
public function connection(): Connection;
|
||||
|
||||
/**
|
||||
* Set the DB connection that should be used by the tenant database manager.
|
||||
|
|
|
|||
|
|
@ -11,19 +11,19 @@ class MicrosoftSQLDatabaseManager extends TenantDatabaseManager
|
|||
public function createDatabase(TenantWithDatabase $tenant): bool
|
||||
{
|
||||
$database = $tenant->database()->getName();
|
||||
$charset = $this->database()->getConfig('charset');
|
||||
$collation = $this->database()->getConfig('collation'); // todo check why these are not used
|
||||
$charset = $this->connection()->getConfig('charset');
|
||||
$collation = $this->connection()->getConfig('collation'); // todo check why these are not used
|
||||
|
||||
return $this->database()->statement("CREATE DATABASE [{$database}]");
|
||||
return $this->connection()->statement("CREATE DATABASE [{$database}]");
|
||||
}
|
||||
|
||||
public function deleteDatabase(TenantWithDatabase $tenant): bool
|
||||
{
|
||||
return $this->database()->statement("DROP DATABASE [{$tenant->database()->getName()}]");
|
||||
return $this->connection()->statement("DROP DATABASE [{$tenant->database()->getName()}]");
|
||||
}
|
||||
|
||||
public function databaseExists(string $name): bool
|
||||
{
|
||||
return (bool) $this->database()->select("SELECT name FROM master.sys.databases WHERE name = '$name'");
|
||||
return (bool) $this->connection()->select("SELECT name FROM master.sys.databases WHERE name = '$name'");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,19 +11,19 @@ class MySQLDatabaseManager extends TenantDatabaseManager
|
|||
public function createDatabase(TenantWithDatabase $tenant): bool
|
||||
{
|
||||
$database = $tenant->database()->getName();
|
||||
$charset = $this->database()->getConfig('charset');
|
||||
$collation = $this->database()->getConfig('collation');
|
||||
$charset = $this->connection()->getConfig('charset');
|
||||
$collation = $this->connection()->getConfig('collation');
|
||||
|
||||
return $this->database()->statement("CREATE DATABASE `{$database}` CHARACTER SET `$charset` COLLATE `$collation`");
|
||||
return $this->connection()->statement("CREATE DATABASE `{$database}` CHARACTER SET `$charset` COLLATE `$collation`");
|
||||
}
|
||||
|
||||
public function deleteDatabase(TenantWithDatabase $tenant): bool
|
||||
{
|
||||
return $this->database()->statement("DROP DATABASE `{$tenant->database()->getName()}`");
|
||||
return $this->connection()->statement("DROP DATABASE `{$tenant->database()->getName()}`");
|
||||
}
|
||||
|
||||
public function databaseExists(string $name): bool
|
||||
{
|
||||
return (bool) $this->database()->select("SELECT SCHEMA_NAME FROM INFORMATION_SCHEMA.SCHEMATA WHERE SCHEMA_NAME = '$name'");
|
||||
return (bool) $this->connection()->select("SELECT SCHEMA_NAME FROM INFORMATION_SCHEMA.SCHEMATA WHERE SCHEMA_NAME = '$name'");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,24 +25,24 @@ class PermissionControlledMicrosoftSQLServerDatabaseManager extends MicrosoftSQL
|
|||
$password = $databaseConfig->getPassword();
|
||||
|
||||
// Create login
|
||||
$this->database()->statement("CREATE LOGIN [$username] WITH PASSWORD = '$password'");
|
||||
$this->connection()->statement("CREATE LOGIN [$username] WITH PASSWORD = '$password'");
|
||||
|
||||
// Create user in the database
|
||||
// Grant the user permissions specified in the $grants array
|
||||
// The 'CONNECT' permission is granted automatically
|
||||
$grants = implode(', ', static::$grants);
|
||||
|
||||
return $this->database()->statement("USE [$database]; CREATE USER [$username] FOR LOGIN [$username]; GRANT $grants TO [$username]");
|
||||
return $this->connection()->statement("USE [$database]; CREATE USER [$username] FOR LOGIN [$username]; GRANT $grants TO [$username]");
|
||||
}
|
||||
|
||||
public function deleteUser(DatabaseConfig $databaseConfig): bool
|
||||
{
|
||||
return $this->database()->statement("DROP LOGIN [{$databaseConfig->getUsername()}]");
|
||||
return $this->connection()->statement("DROP LOGIN [{$databaseConfig->getUsername()}]");
|
||||
}
|
||||
|
||||
public function userExists(string $username): bool
|
||||
{
|
||||
return (bool) $this->database()->select("SELECT sp.name as username FROM sys.server_principals sp WHERE sp.name = '{$username}'");
|
||||
return (bool) $this->connection()->select("SELECT sp.name as username FROM sys.server_principals sp WHERE sp.name = '{$username}'");
|
||||
}
|
||||
|
||||
public function makeConnectionConfig(array $baseConfig, string $databaseName): array
|
||||
|
|
@ -58,7 +58,7 @@ class PermissionControlledMicrosoftSQLServerDatabaseManager extends MicrosoftSQL
|
|||
// Set the database to SINGLE_USER mode to ensure that
|
||||
// No other connections are using the database while we're trying to delete it
|
||||
// Rollback all active transactions
|
||||
$this->database()->statement("ALTER DATABASE [{$tenant->database()->getName()}] SET SINGLE_USER WITH ROLLBACK IMMEDIATE;");
|
||||
$this->connection()->statement("ALTER DATABASE [{$tenant->database()->getName()}] SET SINGLE_USER WITH ROLLBACK IMMEDIATE;");
|
||||
|
||||
return parent::deleteDatabase($tenant);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ class PermissionControlledMySQLDatabaseManager extends MySQLDatabaseManager impl
|
|||
$hostname = $databaseConfig->connection()['host'];
|
||||
$password = $databaseConfig->getPassword();
|
||||
|
||||
$this->database()->statement("CREATE USER `{$username}`@`%` IDENTIFIED BY '{$password}'");
|
||||
$this->connection()->statement("CREATE USER `{$username}`@`%` IDENTIFIED BY '{$password}'");
|
||||
|
||||
$grants = implode(', ', static::$grants);
|
||||
|
||||
|
|
@ -36,24 +36,24 @@ class PermissionControlledMySQLDatabaseManager extends MySQLDatabaseManager impl
|
|||
$grantQuery = "GRANT $grants ON `$database`.* TO `$username`@`%` IDENTIFIED BY '$password'";
|
||||
}
|
||||
|
||||
return $this->database()->statement($grantQuery);
|
||||
return $this->connection()->statement($grantQuery);
|
||||
}
|
||||
|
||||
protected function isVersion8(): bool
|
||||
{
|
||||
$versionSelect = (string) $this->database()->raw('select version()')->getValue($this->database()->getQueryGrammar());
|
||||
$version = $this->database()->select($versionSelect)[0]->{'version()'};
|
||||
$versionSelect = (string) $this->connection()->raw('select version()')->getValue($this->connection()->getQueryGrammar());
|
||||
$version = $this->connection()->select($versionSelect)[0]->{'version()'};
|
||||
|
||||
return version_compare($version, '8.0.0') >= 0;
|
||||
}
|
||||
|
||||
public function deleteUser(DatabaseConfig $databaseConfig): bool
|
||||
{
|
||||
return $this->database()->statement("DROP USER IF EXISTS '{$databaseConfig->getUsername()}'");
|
||||
return $this->connection()->statement("DROP USER IF EXISTS '{$databaseConfig->getUsername()}'");
|
||||
}
|
||||
|
||||
public function userExists(string $username): bool
|
||||
{
|
||||
return (bool) $this->database()->select("SELECT count(*) FROM mysql.user WHERE user = '$username'")[0]->{'count(*)'};
|
||||
return (bool) $this->connection()->select("SELECT count(*) FROM mysql.user WHERE user = '$username'")[0]->{'count(*)'};
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,26 +21,26 @@ class PermissionControlledPostgreSQLDatabaseManager extends PostgreSQLDatabaseMa
|
|||
$schema = $databaseConfig->connection()['search_path'];
|
||||
|
||||
// Host config
|
||||
$connectionName = $this->database()->getConfig('name');
|
||||
$centralDatabase = $this->database()->getConfig('database');
|
||||
$connectionName = $this->connection()->getConfig('name');
|
||||
$centralDatabase = $this->connection()->getConfig('database');
|
||||
|
||||
$this->database()->statement("GRANT CONNECT ON DATABASE \"{$database}\" TO \"{$username}\"");
|
||||
$this->connection()->statement("GRANT CONNECT ON DATABASE \"{$database}\" TO \"{$username}\"");
|
||||
|
||||
// Connect to tenant database
|
||||
config(["database.connections.{$connectionName}.database" => $database]);
|
||||
|
||||
$this->database()->reconnect();
|
||||
$this->connection()->reconnect();
|
||||
|
||||
// Grant permissions to create and use tables in the configured schema ("public" by default) to the user
|
||||
$this->database()->statement("GRANT USAGE, CREATE ON SCHEMA {$schema} TO \"{$username}\"");
|
||||
$this->connection()->statement("GRANT USAGE, CREATE ON SCHEMA {$schema} TO \"{$username}\"");
|
||||
|
||||
// Grant permissions to use sequences in the current schema to the user
|
||||
$this->database()->statement("GRANT USAGE ON ALL SEQUENCES IN SCHEMA {$schema} TO \"{$username}\"");
|
||||
$this->connection()->statement("GRANT USAGE ON ALL SEQUENCES IN SCHEMA {$schema} TO \"{$username}\"");
|
||||
|
||||
// Reconnect to central database
|
||||
config(["database.connections.{$connectionName}.database" => $centralDatabase]);
|
||||
|
||||
$this->database()->reconnect();
|
||||
$this->connection()->reconnect();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,11 +23,11 @@ class PermissionControlledPostgreSQLSchemaManager extends PostgreSQLSchemaManage
|
|||
// Central database name
|
||||
$database = DB::connection(config('tenancy.database.central_connection'))->getDatabaseName();
|
||||
|
||||
$this->database()->statement("GRANT CONNECT ON DATABASE {$database} TO \"{$username}\"");
|
||||
$this->database()->statement("GRANT USAGE, CREATE ON SCHEMA \"{$schema}\" TO \"{$username}\"");
|
||||
$this->database()->statement("GRANT USAGE ON ALL SEQUENCES IN SCHEMA \"{$schema}\" TO \"{$username}\"");
|
||||
$this->connection()->statement("GRANT CONNECT ON DATABASE {$database} TO \"{$username}\"");
|
||||
$this->connection()->statement("GRANT USAGE, CREATE ON SCHEMA \"{$schema}\" TO \"{$username}\"");
|
||||
$this->connection()->statement("GRANT USAGE ON ALL SEQUENCES IN SCHEMA \"{$schema}\" TO \"{$username}\"");
|
||||
|
||||
$tables = $this->database()->select("SELECT table_name FROM information_schema.tables WHERE table_schema = '{$schema}'");
|
||||
$tables = $this->connection()->select("SELECT table_name FROM information_schema.tables WHERE table_schema = '{$schema}'");
|
||||
|
||||
// Grant permissions to any existing tables. This is used with RLS
|
||||
// todo@samuel refactor this along with the todo in TenantDatabaseManager
|
||||
|
|
@ -36,7 +36,7 @@ class PermissionControlledPostgreSQLSchemaManager extends PostgreSQLSchemaManage
|
|||
$tableName = $table->table_name;
|
||||
|
||||
/** @var string $primaryKey */
|
||||
$primaryKey = $this->database()->selectOne(<<<SQL
|
||||
$primaryKey = $this->connection()->selectOne(<<<SQL
|
||||
SELECT column_name
|
||||
FROM information_schema.key_column_usage
|
||||
WHERE table_name = '{$tableName}'
|
||||
|
|
@ -44,11 +44,11 @@ class PermissionControlledPostgreSQLSchemaManager extends PostgreSQLSchemaManage
|
|||
SQL)->column_name;
|
||||
|
||||
// Grant all permissions for all existing tables
|
||||
$this->database()->statement("GRANT ALL ON \"{$schema}\".\"{$tableName}\" TO \"{$username}\"");
|
||||
$this->connection()->statement("GRANT ALL ON \"{$schema}\".\"{$tableName}\" TO \"{$username}\"");
|
||||
|
||||
// Grant permission to reference the primary key for the table
|
||||
// The previous query doesn't grant the references privilege, so it has to be granted here
|
||||
$this->database()->statement("GRANT REFERENCES (\"{$primaryKey}\") ON \"{$schema}\".\"{$tableName}\" TO \"{$username}\"");
|
||||
$this->connection()->statement("GRANT REFERENCES (\"{$primaryKey}\") ON \"{$schema}\".\"{$tableName}\" TO \"{$username}\"");
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -10,16 +10,16 @@ class PostgreSQLDatabaseManager extends TenantDatabaseManager
|
|||
{
|
||||
public function createDatabase(TenantWithDatabase $tenant): bool
|
||||
{
|
||||
return $this->database()->statement("CREATE DATABASE \"{$tenant->database()->getName()}\" WITH TEMPLATE=template0");
|
||||
return $this->connection()->statement("CREATE DATABASE \"{$tenant->database()->getName()}\" WITH TEMPLATE=template0");
|
||||
}
|
||||
|
||||
public function deleteDatabase(TenantWithDatabase $tenant): bool
|
||||
{
|
||||
return $this->database()->statement("DROP DATABASE \"{$tenant->database()->getName()}\"");
|
||||
return $this->connection()->statement("DROP DATABASE \"{$tenant->database()->getName()}\"");
|
||||
}
|
||||
|
||||
public function databaseExists(string $name): bool
|
||||
{
|
||||
return (bool) $this->database()->selectOne("SELECT datname FROM pg_database WHERE datname = '$name'");
|
||||
return (bool) $this->connection()->selectOne("SELECT datname FROM pg_database WHERE datname = '$name'");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,17 +10,17 @@ class PostgreSQLSchemaManager extends TenantDatabaseManager
|
|||
{
|
||||
public function createDatabase(TenantWithDatabase $tenant): bool
|
||||
{
|
||||
return $this->database()->statement("CREATE SCHEMA \"{$tenant->database()->getName()}\"");
|
||||
return $this->connection()->statement("CREATE SCHEMA \"{$tenant->database()->getName()}\"");
|
||||
}
|
||||
|
||||
public function deleteDatabase(TenantWithDatabase $tenant): bool
|
||||
{
|
||||
return $this->database()->statement("DROP SCHEMA \"{$tenant->database()->getName()}\" CASCADE");
|
||||
return $this->connection()->statement("DROP SCHEMA \"{$tenant->database()->getName()}\" CASCADE");
|
||||
}
|
||||
|
||||
public function databaseExists(string $name): bool
|
||||
{
|
||||
return (bool) $this->database()->select("SELECT schema_name FROM information_schema.schemata WHERE schema_name = '$name'");
|
||||
return (bool) $this->connection()->select("SELECT schema_name FROM information_schema.schemata WHERE schema_name = '$name'");
|
||||
}
|
||||
|
||||
public function makeConnectionConfig(array $baseConfig, string $databaseName): array
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ abstract class TenantDatabaseManager implements StatefulTenantDatabaseManager
|
|||
/** The database connection to the server. */
|
||||
protected string $connection;
|
||||
|
||||
public function database(): Connection
|
||||
public function connection(): Connection
|
||||
{
|
||||
if (! isset($this->connection)) {
|
||||
throw new NoConnectionSetException(static::class);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue