1
0
Fork 0
mirror of https://github.com/archtechx/tenancy.git synced 2026-02-04 09:04:03 +00:00

fix: Refactor database management methods to use parameterized queries and add identifier quoting

This commit is contained in:
Hayatunnabi Nabil 2025-11-07 15:41:38 +06:00
parent 8bdacf566b
commit 712d7aabec
3 changed files with 41 additions and 9 deletions

View file

@ -17,18 +17,28 @@ trait ManagesRLSPolicies
{ {
return array_map( return array_map(
fn (stdClass $policy) => $policy->policyname, fn (stdClass $policy) => $policy->policyname,
DB::select("SELECT policyname FROM pg_policies WHERE tablename = '{$table}' AND policyname LIKE '%_rls_policy%'") DB::select(
"SELECT policyname FROM pg_policies WHERE tablename = ? AND policyname LIKE ?",
[$table, '%_rls_policy%']
)
); );
} }
public static function dropRLSPolicies(string $table): int public static function dropRLSPolicies(string $table): int
{ {
$policies = static::getRLSPolicies($table); $policies = static::getRLSPolicies($table);
$quotedTable = static::quoteIdentifier($table);
foreach ($policies as $policy) { foreach ($policies as $policy) {
DB::statement('DROP POLICY ? ON ?', [$policy, $table]); $quotedPolicy = static::quoteIdentifier($policy);
DB::statement("DROP POLICY {$quotedPolicy} ON {$quotedTable}");
} }
return count($policies); return count($policies);
} }
protected static function quoteIdentifier(string $identifier): string
{
return '"' . str_replace('"', '""', $identifier) . '"';
}
} }

View file

@ -10,20 +10,30 @@ class MySQLDatabaseManager extends TenantDatabaseManager
{ {
public function createDatabase(TenantWithDatabase $tenant): bool public function createDatabase(TenantWithDatabase $tenant): bool
{ {
$database = $tenant->database()->getName(); $database = $this->quoteIdentifier($tenant->database()->getName());
$charset = $this->connection()->getConfig('charset'); $charset = $this->connection()->getConfig('charset');
$collation = $this->connection()->getConfig('collation'); $collation = $this->connection()->getConfig('collation');
return $this->connection()->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 public function deleteDatabase(TenantWithDatabase $tenant): bool
{ {
return $this->connection()->statement("DROP DATABASE `{$tenant->database()->getName()}`"); $database = $this->quoteIdentifier($tenant->database()->getName());
return $this->connection()->statement("DROP DATABASE {$database}");
} }
public function databaseExists(string $name): bool public function databaseExists(string $name): bool
{ {
return (bool) $this->connection()->select("SELECT SCHEMA_NAME FROM INFORMATION_SCHEMA.SCHEMATA WHERE SCHEMA_NAME = '$name'"); return (bool) $this->connection()->selectOne(
'SELECT SCHEMA_NAME FROM INFORMATION_SCHEMA.SCHEMATA WHERE SCHEMA_NAME = ? LIMIT 1',
[$name]
);
}
protected function quoteIdentifier(string $identifier): string
{
return '`' . str_replace('`', '``', $identifier) . '`';
} }
} }

View file

@ -10,16 +10,28 @@ class PostgreSQLDatabaseManager extends TenantDatabaseManager
{ {
public function createDatabase(TenantWithDatabase $tenant): bool public function createDatabase(TenantWithDatabase $tenant): bool
{ {
return $this->connection()->statement("CREATE DATABASE \"{$tenant->database()->getName()}\" WITH TEMPLATE=template0"); $database = $this->quoteIdentifier($tenant->database()->getName());
return $this->connection()->statement("CREATE DATABASE {$database} WITH TEMPLATE=template0");
} }
public function deleteDatabase(TenantWithDatabase $tenant): bool public function deleteDatabase(TenantWithDatabase $tenant): bool
{ {
return $this->connection()->statement("DROP DATABASE \"{$tenant->database()->getName()}\""); $database = $this->quoteIdentifier($tenant->database()->getName());
return $this->connection()->statement("DROP DATABASE {$database}");
} }
public function databaseExists(string $name): bool public function databaseExists(string $name): bool
{ {
return (bool) $this->connection()->selectOne("SELECT datname FROM pg_database WHERE datname = '$name'"); return (bool) $this->connection()->selectOne(
'SELECT datname FROM pg_database WHERE datname = ? LIMIT 1',
[$name]
);
}
protected function quoteIdentifier(string $identifier): string
{
return '"' . str_replace('"', '""', $identifier) . '"';
} }
} }