-
-
Notifications
You must be signed in to change notification settings - Fork 487
[4.x] Parameter validation and other DB manager improvements #1459
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
808f527
ad7d229
bdf592c
5adbc14
182f3a2
d5087d1
db03997
0fdb8b2
4a3e6ba
740d53e
8592949
f3f1ab9
75b74f2
322257f
46f73c4
4bdb877
50ea524
bacbf93
37a4c7d
2bd3a86
76c324d
d3607f8
e8168eb
9611a05
f3836cc
2bdda23
1a01164
665404e
fbd1e02
fc6a931
f5f5f1d
52f6857
0ce3d86
2ae1f79
b1f0d0a
7363318
48b4837
7683bef
e48d822
9a9adc0
7f93f44
7660ddd
26c161a
429e098
ea20eb1
405aaaf
2b3466f
338526d
fec170a
98a808b
6ed9975
de91348
bdbfbd4
e59195e
66ae88a
0331875
bbd8f6f
587f347
099a666
649c802
519c819
d9ae274
9055b61
6e82a9e
b4244be
42a2c8e
b7045c5
4386a3b
9ea085e
f9636b1
b3111f1
407197b
49356a5
cf7e086
d28abde
36782eb
3fb0176
88156d1
b3d1158
13e32dd
fbffeb8
48b8aac
565bc41
7972da5
540e363
93f77a5
1ae7d58
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,92 @@ | ||
| <?php | ||
|
|
||
| declare(strict_types=1); | ||
|
|
||
| namespace Stancl\Tenancy\Database\Concerns; | ||
|
|
||
| use Illuminate\Support\Arr; | ||
| use InvalidArgumentException; | ||
|
|
||
| /** | ||
| * Provides methods to validate database parameters (e.g. database names, usernames, passwords) | ||
| * before using them in SQL statements (or in file paths in the case of SQLiteDatabaseManager). | ||
| * | ||
| * Used where parameters can be provided by users, and where parameter binding cannot be used. | ||
| * | ||
| * @see \Stancl\Tenancy\Database\TenantDatabaseManagers\TenantDatabaseManager | ||
| * @see \Stancl\Tenancy\Database\TenantDatabaseManagers\SQLiteDatabaseManager | ||
| */ | ||
| trait ValidatesDatabaseParameters | ||
| { | ||
| /** | ||
| * Characters allowed in parameters. | ||
| * | ||
| * Used as the default allowlist in validateParameter(), which validates non-password | ||
| * parameters such as database names or usernames. | ||
| * | ||
| * Since non-password parameters don't need to use as many special characters, we use | ||
| * a stricter allowlist here. | ||
| */ | ||
| public static string $allowedParameterCharacters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-'; | ||
|
|
||
| /** | ||
| * Characters allowed in database user passwords. | ||
| * | ||
| * The allowlist for passwords is less strict than for other parameters | ||
| * because it's more common to use more special characters in passwords. | ||
| */ | ||
| public static string $allowedPasswordCharacters = ' !#$%&()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_abcdefghijklmnopqrstuvwxyz{|}~'; | ||
|
|
||
| /** | ||
| * Ensure that parameters (database names, usernames, etc.) | ||
| * only contain allowed characters before used in SQL statements | ||
| * (or paths in the case of SQLiteDatabaseManager). | ||
| * | ||
| * By default, only the characters in allowedParameterCharacters() are allowed. | ||
| * | ||
| * @throws InvalidArgumentException | ||
| */ | ||
| protected function validateParameter(string|array|null $parameters, string|null $allowedCharacters = null): void | ||
| { | ||
| if ($parameters === null) { | ||
| throw new InvalidArgumentException('Parameter cannot be null.'); | ||
| } | ||
|
|
||
| $allowedCharacters ??= static::$allowedParameterCharacters; | ||
|
|
||
| foreach (Arr::wrap($parameters) as $parameter) { | ||
| if (is_null($parameter)) { | ||
| throw new InvalidArgumentException('Parameter cannot be null.'); | ||
| } | ||
|
|
||
| if (is_numeric($parameter)) { | ||
| $parameter = (string) $parameter; | ||
| } | ||
|
Comment on lines
+58
to
+60
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you describe that case in a bit more detail? I think
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
You're right about that -- with MySQL, it'd create an "anonymous" user (empty string name), which sounds invalid, but the user creation would pass. Postgres would instead reject the null/empty string. So maybe actually worth considering throwing an exception here instead of just skipping?
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hmm yeah I was thinking if that could break anything but we selectively choose when to validate some parameter so all those places that call So for optional things like charset you'd only validate the param after checking that there is some charset set — it's not null — while for things like username/password those places simply expect the values to not be null, so an exception seems appropriate to validate that expectation.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Updated the logic accordingly 48b8aac |
||
|
|
||
| if (! is_string($parameter)) { | ||
| // E.g. if a parameter is retrieved from the config, it isn't necessarily a string | ||
|
lukinovec marked this conversation as resolved.
|
||
| throw new InvalidArgumentException('Parameter has to be a string.'); | ||
| } | ||
|
|
||
| foreach (str_split($parameter) as $character) { | ||
| if (! str_contains($allowedCharacters, $character)) { | ||
| throw new InvalidArgumentException("Forbidden character '{$character}' in parameter."); | ||
| } | ||
| } | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * Ensure password only contains allowed characters (allowedPasswordCharacters()) | ||
| * before being used in SQL statements. | ||
| * | ||
| * Used in permission controlled managers as a shorthand for calling validateParameter() | ||
| * with the less strict allowlist to validate database user passwords. | ||
| * | ||
| * @throws InvalidArgumentException | ||
| */ | ||
| protected function validatePassword(string|null $password): void | ||
| { | ||
| $this->validateParameter($password, allowedCharacters: static::$allowedPasswordCharacters); | ||
| } | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.