mirror of
https://github.com/archtechx/tenancy.git
synced 2026-05-06 15:24:03 +00:00
Validate in-memory db names, move SQLite-specific methods to the SQLiteManager
This commit is contained in:
parent
7363318f6e
commit
48b4837905
2 changed files with 49 additions and 35 deletions
|
|
@ -28,16 +28,6 @@ trait ValidatesDatabaseParameters
|
||||||
return 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-';
|
return 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Characters allowed in filenames (SQLite databases).
|
|
||||||
*
|
|
||||||
* Includes dots to support file extensions (e.g. '.sqlite').
|
|
||||||
*/
|
|
||||||
protected static function allowedFilenameCharacters(): string
|
|
||||||
{
|
|
||||||
return 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-.';
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Characters allowed in database user passwords.
|
* Characters allowed in database user passwords.
|
||||||
*
|
*
|
||||||
|
|
@ -62,7 +52,7 @@ trait ValidatesDatabaseParameters
|
||||||
*
|
*
|
||||||
* @throws InvalidArgumentException
|
* @throws InvalidArgumentException
|
||||||
*/
|
*/
|
||||||
protected function validateParameter(string|array|null $parameters, string|null $allowedCharacters = null): void
|
protected static function validateParameter(string|array|null $parameters, string|null $allowedCharacters = null): void
|
||||||
{
|
{
|
||||||
$allowedCharacters ??= static::allowedParameterCharacters();
|
$allowedCharacters ??= static::allowedParameterCharacters();
|
||||||
|
|
||||||
|
|
@ -95,28 +85,8 @@ trait ValidatesDatabaseParameters
|
||||||
*
|
*
|
||||||
* @throws InvalidArgumentException
|
* @throws InvalidArgumentException
|
||||||
*/
|
*/
|
||||||
protected function validatePassword(string|null $password): void
|
protected static function validatePassword(string|null $password): void
|
||||||
{
|
{
|
||||||
$this->validateParameter($password, static::allowedPasswordCharacters());
|
static::validateParameter($password, allowedCharacters: static::allowedPasswordCharacters());
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Ensure filename only contains allowed characters (static::allowedFilenameCharacters())
|
|
||||||
* and is not a directory name before used in file paths (e.g. SQLite database names).
|
|
||||||
*
|
|
||||||
* @throws InvalidArgumentException
|
|
||||||
* @see Stancl\Tenancy\Database\TenantDatabaseManagers\SQLiteDatabaseManager
|
|
||||||
*/
|
|
||||||
protected function validateFilename(string $filename): void
|
|
||||||
{
|
|
||||||
$this->validateParameter($filename, static::allowedFilenameCharacters());
|
|
||||||
|
|
||||||
if ($filename === '') {
|
|
||||||
throw new InvalidArgumentException('Filename cannot be empty.');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (is_dir($filename)) {
|
|
||||||
throw new InvalidArgumentException("Filename ('{$filename}') cannot be a directory.");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ use Stancl\Tenancy\Database\Concerns\ValidatesDatabaseParameters;
|
||||||
use Stancl\Tenancy\Database\Contracts\TenantDatabaseManager;
|
use Stancl\Tenancy\Database\Contracts\TenantDatabaseManager;
|
||||||
use Stancl\Tenancy\Database\Contracts\TenantWithDatabase;
|
use Stancl\Tenancy\Database\Contracts\TenantWithDatabase;
|
||||||
use Throwable;
|
use Throwable;
|
||||||
|
use InvalidArgumentException;
|
||||||
|
|
||||||
class SQLiteDatabaseManager implements TenantDatabaseManager
|
class SQLiteDatabaseManager implements TenantDatabaseManager
|
||||||
{
|
{
|
||||||
|
|
@ -60,6 +61,16 @@ class SQLiteDatabaseManager implements TenantDatabaseManager
|
||||||
*/
|
*/
|
||||||
public static Closure|null $closeInMemoryConnectionUsing = null;
|
public static Closure|null $closeInMemoryConnectionUsing = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Characters allowed in database names.
|
||||||
|
*
|
||||||
|
* Includes dots to support file extensions (e.g. '.sqlite').
|
||||||
|
*/
|
||||||
|
protected static function allowedDatabaseNameCharacters(): string
|
||||||
|
{
|
||||||
|
return 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-.';
|
||||||
|
}
|
||||||
|
|
||||||
public function createDatabase(TenantWithDatabase $tenant): bool
|
public function createDatabase(TenantWithDatabase $tenant): bool
|
||||||
{
|
{
|
||||||
/** @var TenantWithDatabase&Model $tenant */
|
/** @var TenantWithDatabase&Model $tenant */
|
||||||
|
|
@ -136,6 +147,8 @@ class SQLiteDatabaseManager implements TenantDatabaseManager
|
||||||
(static::$persistInMemoryConnectionUsing)(new PDO($dsn), $dsn);
|
(static::$persistInMemoryConnectionUsing)(new PDO($dsn), $dsn);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
$this->validateDatabaseName($databaseName);
|
||||||
|
|
||||||
$baseConfig['database'] = database_path($databaseName);
|
$baseConfig['database'] = database_path($databaseName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -148,13 +161,44 @@ class SQLiteDatabaseManager implements TenantDatabaseManager
|
||||||
return rtrim(static::$path, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR . $name;
|
return rtrim(static::$path, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR . $name;
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->validateFilename($name);
|
$this->validateDatabaseName($name);
|
||||||
|
|
||||||
return database_path($name);
|
return database_path($name);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function isInMemory(string $name): bool
|
public static function isInMemory(string $name): bool
|
||||||
{
|
{
|
||||||
return $name === ':memory:' || str_starts_with($name, 'file:_tenancy_inmemory_');
|
if ($name === ':memory:') {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (str_starts_with($name, 'file:_tenancy_inmemory_') &&
|
||||||
|
str_ends_with($name, '?mode=memory&cache=shared')) {
|
||||||
|
// Named in-memory DBs are formatted like 'file:_tenancy_inmemory_tenant123?mode=memory&cache=shared'
|
||||||
|
static::validateDatabaseName($name, ':?=&');
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ensure database name only contains allowed characters
|
||||||
|
* (static::allowedDatabaseNameCharacters() + $extraAllowedCharacters) and is not a directory name.
|
||||||
|
*
|
||||||
|
* @throws InvalidArgumentException
|
||||||
|
*/
|
||||||
|
protected static function validateDatabaseName(string $name, string $extraAllowedCharacters = ''): void
|
||||||
|
{
|
||||||
|
static::validateParameter($name, static::allowedDatabaseNameCharacters() . $extraAllowedCharacters);
|
||||||
|
|
||||||
|
if ($name === '') {
|
||||||
|
throw new InvalidArgumentException('Database name cannot be empty.');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_dir($name)) {
|
||||||
|
throw new InvalidArgumentException("Database name cannot be a directory.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue