From 5c46df42d9ca8d3be75b16347460d1d0ef8dc7ff Mon Sep 17 00:00:00 2001 From: Eric Wang Date: Mon, 1 Aug 2022 16:22:05 +0000 Subject: [PATCH] Add repositories and exceptions --- .../Repository/RepositoryInterface.php | 169 ++++++++++++++++++ app/Exceptions/ConvoyException.php | 9 + .../Model/DataValidationException.php | 78 ++++++++ .../Repository/RecordNotFoundException.php | 29 +++ .../Repository/RepositoryException.php | 9 + .../Nodes/Addresses/AddressController.php | 5 +- .../Proxmox/ProxmoxRepository.php | 80 +++++++++ app/Repositories/Repository.php | 137 ++++++++++++++ routes/api-application.php | 2 +- 9 files changed, 515 insertions(+), 3 deletions(-) diff --git a/app/Contracts/Repository/RepositoryInterface.php b/app/Contracts/Repository/RepositoryInterface.php index e69de29b..e48b968f 100644 --- a/app/Contracts/Repository/RepositoryInterface.php +++ b/app/Contracts/Repository/RepositoryInterface.php @@ -0,0 +1,169 @@ +getKey(), + $validator->errors()->toJson() + ); + + parent::__construct($message); + + $this->validator = $validator; + $this->model = $model; + } + + /** + * Return the validator message bag. + * + * @return \Illuminate\Support\MessageBag + */ + public function getMessageBag() + { + return $this->validator->errors(); + } + + /** + * Return the status code for this request. + * + * @return int + */ + public function getStatusCode(): int + { + return 500; + } + + /** + * @return array + */ + public function getHeaders(): array + { + return []; + } + + public function getValidator(): Validator + { + return $this->validator; + } + + public function getModel(): Model + { + return $this->model; + } +} \ No newline at end of file diff --git a/app/Exceptions/Repository/RecordNotFoundException.php b/app/Exceptions/Repository/RecordNotFoundException.php index e69de29b..1935fd94 100644 --- a/app/Exceptions/Repository/RecordNotFoundException.php +++ b/app/Exceptions/Repository/RecordNotFoundException.php @@ -0,0 +1,29 @@ +allowedFilters(['server_id', 'node_id', 'address', 'cidr', 'gateway', 'type']) ->allowedSorts(['id', 'server_id', 'node_id']) + ->where('node_id', $node->id) ->paginate($request->query('per_page') ?? 50); return $addresses; } - public function show(IPAddress $address) + public function show(Node $node, IPAddress $address) { return $this->returnContent([ 'data' => $address, diff --git a/app/Repositories/Proxmox/ProxmoxRepository.php b/app/Repositories/Proxmox/ProxmoxRepository.php index e69de29b..da7d4524 100644 --- a/app/Repositories/Proxmox/ProxmoxRepository.php +++ b/app/Repositories/Proxmox/ProxmoxRepository.php @@ -0,0 +1,80 @@ +app = $application; + } + + /** + * Set the server model this request is stemming from. + * + * @return $this + */ + public function setServer(Server $server): static + { + $this->server = $server; + + $this->setNode($this->server->node); + + return $this; + } + + /** + * Set the node model this request is stemming from. + * + * @return $this + */ + public function setNode(Node $node): static + { + $this->node = $node; + + return $this; + } + + /** + * Return an instance of the Guzzle HTTP Client to be used for requests. + */ + public function getHttpClient(array $headers = []): Client + { + Assert::isInstanceOf($this->node, Node::class); + + return new Client([ + 'base_uri' => $this->node->getConnectionAddress(), + 'timeout' => config('pterodactyl.guzzle.timeout'), + 'connect_timeout' => config('pterodactyl.guzzle.connect_timeout'), + 'headers' => array_merge($headers, [ + 'Authorization' => 'Bearer ' . $this->node->getDecryptedKey(), + 'Accept' => 'application/json', + 'Content-Type' => 'application/json', + ]), + ]); + } +} \ No newline at end of file diff --git a/app/Repositories/Repository.php b/app/Repositories/Repository.php index e69de29b..0294fd29 100644 --- a/app/Repositories/Repository.php +++ b/app/Repositories/Repository.php @@ -0,0 +1,137 @@ +app = $application; + + $this->initializeModel($this->model()); + } + + /** + * Return the model backing this repository. + * + * @return string|Closure|object + */ + abstract public function model(); + + /** + * Return the model being used for this repository. + * + * @return mixed + */ + public function getModel(): mixed + { + return $this->model; + } + + /** + * Setup column selection functionality. + * + * @param array|string $columns + * + * @return $this + */ + public function setColumns($columns = ['*']): Repository|static + { + $clone = clone $this; + $clone->columns = is_array($columns) ? $columns : func_get_args(); + + return $clone; + } + + /** + * Return the columns to be selected in the repository call. + * + * @return array + */ + public function getColumns(): array + { + return $this->columns; + } + + /** + * Stop repository update functions from returning a fresh + * model when changes are committed. + * + * @return $this + */ + public function withoutFreshModel(): Repository|static + { + return $this->setFreshModel(false); + } + + /** + * Return a fresh model with a repository updates a model. + * + * @return $this + */ + public function withFreshModel() + { + return $this->setFreshModel(true); + } + + /** + * Set whether or not the repository should return a fresh model + * when changes are committed. + * + * @return $this + */ + public function setFreshModel(bool $fresh = true) + { + $clone = clone $this; + $clone->withFresh = $fresh; + + return $clone; + } + + /** + * Take the provided model and make it accessible to the rest of the repository. + * + * @param array $model + * + * @return mixed + */ + protected function initializeModel(...$model): mixed + { + switch (count($model)) { + case 1: + return $this->model = $this->app->make($model[0]); + case 2: + return $this->model = call_user_func([$this->app->make($model[0]), $model[1]]); + default: + throw new InvalidArgumentException('Model must be a FQDN or an array with a count of two.'); + } + } +} \ No newline at end of file diff --git a/routes/api-application.php b/routes/api-application.php index 8ad40fad..bf90350f 100644 --- a/routes/api-application.php +++ b/routes/api-application.php @@ -52,7 +52,7 @@ Route::group(['prefix' => '/servers'], function () { /* |-------------------------------------------------------------------------- -| Server Controller Routes +| Node Controller Routes |-------------------------------------------------------------------------- | | Endpoint: /api/application/servers