mirror of
https://github.com/archtechx/tenancy.git
synced 2026-05-07 03:04:04 +00:00
Postgres RLS + permission controlled database managers (#33)
This PR adds Postgres RLS (trait manager + table manager approach) and permission controlled managers for PostgreSQL. --------- Co-authored-by: lukinovec <lukinovec@gmail.com> Co-authored-by: PHP CS Fixer <phpcsfixer@example.com>
This commit is contained in:
parent
34297d3e1a
commit
7317d2638a
39 changed files with 2511 additions and 112 deletions
83
src/Database/Concerns/ManagesPostgresUsers.php
Normal file
83
src/Database/Concerns/ManagesPostgresUsers.php
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Stancl\Tenancy\Database\Concerns;
|
||||
|
||||
use Stancl\Tenancy\Database\DatabaseConfig;
|
||||
use Stancl\Tenancy\Database\TenantDatabaseManagers\TenantDatabaseManager;
|
||||
|
||||
/**
|
||||
* @method \Illuminate\Database\Connection database()
|
||||
* @mixin TenantDatabaseManager
|
||||
*/
|
||||
trait ManagesPostgresUsers
|
||||
{
|
||||
/**
|
||||
* Grant database/schema and table permissions to the user whose credentials are stored in the passed DatabaseConfig.
|
||||
*
|
||||
* With schema manager, the schema name is stored in the 'search_path' key of the connection config,
|
||||
* but it's still accessible using $databaseConfig->getName().
|
||||
*/
|
||||
abstract protected function grantPermissions(DatabaseConfig $databaseConfig): bool;
|
||||
|
||||
public function createUser(DatabaseConfig $databaseConfig): bool
|
||||
{
|
||||
/** @var string $username */
|
||||
$username = $databaseConfig->getUsername();
|
||||
$password = $databaseConfig->getPassword();
|
||||
|
||||
$createUser = ! $this->userExists($username);
|
||||
|
||||
if ($createUser) {
|
||||
$this->database()->statement("CREATE USER \"{$username}\" LOGIN PASSWORD '{$password}'");
|
||||
}
|
||||
|
||||
$this->grantPermissions($databaseConfig);
|
||||
|
||||
return $createUser;
|
||||
}
|
||||
|
||||
public function deleteUser(DatabaseConfig $databaseConfig): bool
|
||||
{
|
||||
/** @var TenantDatabaseManager $this */
|
||||
|
||||
// Tenant DB username
|
||||
$username = $databaseConfig->getUsername();
|
||||
|
||||
// Tenant host connection config
|
||||
$connectionName = $this->database()->getConfig('name');
|
||||
$centralDatabase = $this->database()->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()),
|
||||
);
|
||||
|
||||
// Connect to the tenant DB/schema
|
||||
$this->database()->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}\"");
|
||||
|
||||
// Delete the user
|
||||
$userDeleted = $this->database()->statement("DROP USER \"{$username}\"");
|
||||
|
||||
config()->set(
|
||||
"database.connections.{$connectionName}",
|
||||
$this->makeConnectionConfig($this->database()->getConfig(), $centralDatabase),
|
||||
);
|
||||
|
||||
// Reconnect to the central database
|
||||
$this->database()->reconnect();
|
||||
|
||||
return $userDeleted;
|
||||
}
|
||||
|
||||
public function userExists(string $username): bool
|
||||
{
|
||||
return (bool) $this->database()->selectOne("SELECT usename FROM pg_user WHERE usename = '{$username}'");
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue