validateDatabaseLimit = $validate; return $this; } /** * Create a new database that is linked to a specific host. * * @param array{database?: string, database_host_id: int} $data * * @throws \Throwable * @throws \App\Exceptions\Service\Database\TooManyDatabasesException * @throws \App\Exceptions\Service\Database\DatabaseClientFeatureNotEnabledException */ public function create(Server $server, array $data): Database { if (!config('panel.client_features.databases.enabled')) { throw new DatabaseClientFeatureNotEnabledException(); } if ($this->validateDatabaseLimit) { // If the server has a limit assigned and we've already reached that limit, throw back // an exception and kill the process. if (!is_null($server->database_limit) && $server->databases()->count() >= $server->database_limit) { throw new TooManyDatabasesException(); } } // Protect against developer mistakes... if (empty($data['database']) || !preg_match(self::MATCH_NAME_REGEX, $data['database'])) { throw new \InvalidArgumentException('The database name passed to DatabaseManagementService::handle MUST be prefixed with "s{server_id}_".'); } $data = array_merge($data, [ 'server_id' => $server->id, 'username' => sprintf('u%d_%s', $server->id, str_random(10)), 'password' => Utilities::randomStringWithSpecialCharacters(24), ]); return $this->connection->transaction(function () use ($data) { $database = $this->createModel($data); $database->createDatabase($database->database); $database->createUser( $database->username, $database->remote, $database->password, $database->max_connections ); $database->assignUserToDatabase($database->database, $database->username, $database->remote); $database->flush(); Activity::event('server:database.create') ->subject($database) ->property('name', $database->database) ->log(); return $database; }); } /** * Delete a database from the given host server. * * @throws \Exception */ public function delete(Database $database): ?bool { $database->dropDatabase($database->database); $database->dropUser($database->username, $database->remote); $database->flush(); return $database->delete(); } /** * Create the database if there is not an identical match in the DB. While you can technically * have the same name across multiple hosts, for the sake of keeping this logic easy to understand * and avoiding user confusion we will ignore the specific host and just look across all hosts. * * @param array{server_id: int, database: string} $data * * @throws \App\Exceptions\Repository\DuplicateDatabaseNameException * @throws \Throwable */ protected function createModel(array $data): Database { $exists = Database::query()->where('server_id', $data['server_id']) ->where('database', $data['database']) ->exists(); if ($exists) { throw new DuplicateDatabaseNameException('A database with that name already exists for this server.'); } $database = (new Database())->forceFill($data); $database->saveOrFail(); return $database; } }