Add Max Concurrent Connections for database users

Closes #1849

Allows database users to be limited to a number of concurrent connections to prevent one user from connecting hundreds of time and bottlenecking the MySQL server.
This commit is contained in:
AreYouScared 2020-04-22 06:00:04 -04:00
parent 2c3a9228ec
commit f0e4764a11
10 changed files with 56 additions and 6 deletions

View file

@ -68,9 +68,10 @@ interface DatabaseRepositoryInterface extends RepositoryInterface
* @param string $username
* @param string $remote
* @param string $password
* @param string $max_connections
* @return bool
*/
public function createUser(string $username, string $remote, string $password): bool;
public function createUser(string $username, string $remote, string $password, string $max_connections): bool;
/**
* Give a specific user access to a given database.

View file

@ -30,7 +30,7 @@ class Database extends Model
* @var array
*/
protected $fillable = [
'server_id', 'database_host_id', 'database', 'username', 'password', 'remote',
'server_id', 'database_host_id', 'database', 'username', 'password', 'remote', 'max_connections',
];
/**
@ -51,6 +51,7 @@ class Database extends Model
'database_host_id' => 'required|exists:database_hosts,id',
'database' => 'required|string|alpha_dash|between:3,100',
'username' => 'string|alpha_dash|between:3,100',
'max_connections' => 'string',
'remote' => 'required|string|regex:/^[0-9%.]{1,15}$/',
'password' => 'string',
];

View file

@ -135,11 +135,12 @@ class DatabaseRepository extends EloquentRepository implements DatabaseRepositor
* @param string $username
* @param string $remote
* @param string $password
* @param string $max_connections
* @return bool
*/
public function createUser(string $username, string $remote, string $password): bool
public function createUser(string $username, string $remote, string $password, string $max_connections): bool
{
return $this->run(sprintf('CREATE USER `%s`@`%s` IDENTIFIED BY \'%s\'', $username, $remote, $password));
return $this->run(sprintf('CREATE USER `%s`@`%s` IDENTIFIED BY \'%s\' WITH MAX_USER_CONNECTIONS %s', $username, $remote, $password, $max_connections));
}
/**

View file

@ -84,7 +84,8 @@ class DatabaseManagementService
$this->repository->createUser(
$database->username,
$database->remote,
$this->encrypter->decrypt($database->password)
$this->encrypter->decrypt($database->password),
$database->max_connections
);
$this->repository->assignUserToDatabase(
$database->database,

View file

@ -71,7 +71,7 @@ class DatabasePasswordService
]);
$this->repository->dropUser($database->username, $database->remote);
$this->repository->createUser($database->username, $database->remote, $password);
$this->repository->createUser($database->username, $database->remote, $password, $database->max_connections);
$this->repository->assignUserToDatabase($database->database, $database->username, $database->remote);
$this->repository->flush();
});

View file

@ -56,6 +56,7 @@ class ServerDatabaseTransformer extends BaseTransformer
'database' => $model->database,
'username' => $model->username,
'remote' => $model->remote,
'max_connections' => $model->max_connections,
'created_at' => Chronos::createFromFormat(Chronos::DEFAULT_TO_STRING_FORMAT, $model->created_at)
->setTimezone(config('app.timezone'))
->toIso8601String(),