mirror of
https://github.com/archtechx/tenancy.git
synced 2026-05-06 16:24:03 +00:00
Add validateFilename()
Use validateFilename instead of validateParameter in SQLiteDatabaseManager. Directories are no longer considered valid SQLite database names.
This commit is contained in:
parent
2bd3a868ec
commit
76c324d758
3 changed files with 37 additions and 18 deletions
|
|
@ -28,6 +28,16 @@ trait ValidatesDatabaseParameters
|
||||||
return 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-';
|
return 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Characters allowed in filenames (SQLite databases).
|
||||||
|
*
|
||||||
|
* Allows dots to support file extensions (e.g. '.sqlite').
|
||||||
|
*/
|
||||||
|
protected static function filenameAllowlist(): string
|
||||||
|
{
|
||||||
|
return 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-.';
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Characters allowed in database user passwords.
|
* Characters allowed in database user passwords.
|
||||||
*
|
*
|
||||||
|
|
@ -66,7 +76,7 @@ trait ValidatesDatabaseParameters
|
||||||
|
|
||||||
foreach (str_split($parameter) as $char) {
|
foreach (str_split($parameter) as $char) {
|
||||||
if (! str_contains($allowlist, $char)) {
|
if (! str_contains($allowlist, $char)) {
|
||||||
throw new InvalidArgumentException("Forbidden character '{$char}' in database parameter.");
|
throw new InvalidArgumentException("Forbidden character '{$char}' in parameter.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -75,8 +85,8 @@ trait ValidatesDatabaseParameters
|
||||||
/**
|
/**
|
||||||
* Ensure password only contains allowed characters before used in SQL statements.
|
* Ensure password only contains allowed characters before used in SQL statements.
|
||||||
*
|
*
|
||||||
* Used as a shorthand for calling validateParameter() with the less strict allowlist
|
* Used in permission controlled managers as a shorthand for calling validateParameter()
|
||||||
* to validate database user passwords.
|
* with the less strict allowlist to validate database user passwords.
|
||||||
*
|
*
|
||||||
* @throws InvalidArgumentException
|
* @throws InvalidArgumentException
|
||||||
*/
|
*/
|
||||||
|
|
@ -84,4 +94,20 @@ trait ValidatesDatabaseParameters
|
||||||
{
|
{
|
||||||
$this->validateParameter($password, static::passwordAllowlist());
|
$this->validateParameter($password, static::passwordAllowlist());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ensure filename only contains allowed characters and is not a directory name
|
||||||
|
* before used in file paths (e.g. SQLite databases).
|
||||||
|
*
|
||||||
|
* @throws InvalidArgumentException
|
||||||
|
* @see Stancl\Tenancy\Database\TenantDatabaseManagers\SQLiteDatabaseManager
|
||||||
|
*/
|
||||||
|
protected function validateFilename(string|null $filename): void
|
||||||
|
{
|
||||||
|
if (is_dir($filename)) {
|
||||||
|
throw new InvalidArgumentException("Filename '{$filename}' is a directory.");
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->validateParameter($filename, static::filenameAllowlist());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -60,11 +60,6 @@ class SQLiteDatabaseManager implements TenantDatabaseManager
|
||||||
*/
|
*/
|
||||||
public static Closure|null $closeInMemoryConnectionUsing = null;
|
public static Closure|null $closeInMemoryConnectionUsing = null;
|
||||||
|
|
||||||
protected static function parameterAllowlist(): string
|
|
||||||
{
|
|
||||||
return 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-.';
|
|
||||||
}
|
|
||||||
|
|
||||||
public function createDatabase(TenantWithDatabase $tenant): bool
|
public function createDatabase(TenantWithDatabase $tenant): bool
|
||||||
{
|
{
|
||||||
/** @var TenantWithDatabase&Model $tenant */
|
/** @var TenantWithDatabase&Model $tenant */
|
||||||
|
|
@ -92,8 +87,6 @@ class SQLiteDatabaseManager implements TenantDatabaseManager
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->validateParameter($name);
|
|
||||||
|
|
||||||
return file_put_contents($this->getPath($name), '') !== false;
|
return file_put_contents($this->getPath($name), '') !== false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -109,8 +102,6 @@ class SQLiteDatabaseManager implements TenantDatabaseManager
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->validateParameter($name);
|
|
||||||
|
|
||||||
$path = $this->getPath($name);
|
$path = $this->getPath($name);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
@ -132,8 +123,6 @@ class SQLiteDatabaseManager implements TenantDatabaseManager
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->validateParameter($name);
|
|
||||||
|
|
||||||
return file_exists($this->getPath($name));
|
return file_exists($this->getPath($name));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -159,6 +148,8 @@ 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);
|
||||||
|
|
||||||
return database_path($name);
|
return database_path($name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -615,15 +615,17 @@ test('database managers validate parameters that cannot be bound', function ($dr
|
||||||
}
|
}
|
||||||
})->with('database_managers');
|
})->with('database_managers');
|
||||||
|
|
||||||
test('sqlite database manager validates the name in databaseExists', function () {
|
test('sqlite database manager validates database filenames', function () {
|
||||||
$manager = app(SQLiteDatabaseManager::class);
|
$manager = app(SQLiteDatabaseManager::class);
|
||||||
|
|
||||||
expect(fn () => $manager->databaseExists("../invalid-db-name.sqlite"))
|
// Dots are allowed in database names
|
||||||
->toThrow(InvalidArgumentException::class);
|
|
||||||
|
|
||||||
expect(fn () => $manager->databaseExists('valid-db_name.sqlite'))
|
expect(fn () => $manager->databaseExists('valid-db_name.sqlite'))
|
||||||
->not()->toThrow(InvalidArgumentException::class);
|
->not()->toThrow(InvalidArgumentException::class);
|
||||||
|
|
||||||
|
// Directories are not allowed as database names
|
||||||
|
expect(fn () => $manager->databaseExists(".."))
|
||||||
|
->toThrow(InvalidArgumentException::class);
|
||||||
|
|
||||||
// In-memory database names aren't validated
|
// In-memory database names aren't validated
|
||||||
expect(fn () => $manager->databaseExists('../_tenancy_inmemory_'))
|
expect(fn () => $manager->databaseExists('../_tenancy_inmemory_'))
|
||||||
->not()->toThrow(InvalidArgumentException::class);
|
->not()->toThrow(InvalidArgumentException::class);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue