Skip to content

Commit

Permalink
Added site health check job
Browse files Browse the repository at this point in the history
  • Loading branch information
SniperSister committed Nov 16, 2024
1 parent a08b590 commit f50069a
Show file tree
Hide file tree
Showing 15 changed files with 491 additions and 95 deletions.
34 changes: 34 additions & 0 deletions app/Console/Commands/PerformSiteHealthCheck.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?php

namespace App\Console\Commands;

use App\Jobs\CheckSiteHealth;
use App\Models\Site;
use Illuminate\Console\Command;

class PerformSiteHealthCheck extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'app:check-site-health {siteId}';

/**
* The console command description.
*
* @var string
*/
protected $description = 'Check site health for given site id';

/**
* Execute the console command.
*/
public function handle()
{
CheckSiteHealth::dispatchSync(
Site::findOrFail($this->input->getArgument('siteId'))
);
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?php

namespace App\Http\Controllers;
namespace app\Controllers;

abstract class Controller
{
Expand Down
13 changes: 13 additions & 0 deletions app/Enum/HttpMethod.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?php

namespace App\Enum;

enum HttpMethod
{
case POST;
case GET;
case PATCH;
case HEAD;
case PUT;
case DELETE;
}
36 changes: 36 additions & 0 deletions app/Http/Middleware/HorizonBasicAuthMiddleware.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?php

namespace App\Http\Middleware;

use Closure;

class HorizonBasicAuthMiddleware
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
$authenticationHasPassed = false;

if ($request->header('PHP_AUTH_USER', null) && $request->header('PHP_AUTH_PW', null)) {
$username = $request->header('PHP_AUTH_USER');
$password = $request->header('PHP_AUTH_PW');

if ($username === config('horizon.basic_auth.username')
&& $password === config('horizon.basic_auth.password')) {
$authenticationHasPassed = true;
}
}

if ($authenticationHasPassed === false) {
return response()->make('Invalid credentials.', 401, ['WWW-Authenticate' => 'Basic']);
}

return $next($request);
}
}
48 changes: 48 additions & 0 deletions app/Jobs/CheckSiteHealth.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<?php declare(strict_types=1);

namespace App\Jobs;

use App\Enum\HttpMethod;
use App\Models\Site;
use GuzzleHttp\Exception\RequestException;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Queue\Queueable;

class CheckSiteHealth implements ShouldQueue
{
use Queueable;

/**
* Create a new job instance.
*/
public function __construct(protected readonly Site $site)
{
}

/**
* Execute the job.
*/
public function handle(): void
{
$response = $this->site->performWebserviceRequest(
HttpMethod::GET,
'health.json'
);

$healthData = collect($response);

// Perform a sanity check
if (!$healthData->has('cms_version')) {
throw new \Exception("Invalid health response content");
}

// Write updated data to DB
$this->site->update($healthData->only([
'php_version',
'db_type',
'db_version',
'cms_version',
'server_os'
])->toArray());
}
}
27 changes: 27 additions & 0 deletions app/Jobs/UpdateSite.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php declare(strict_types=1);

namespace App\Jobs;

use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Queue\Queueable;

class UpdateSite implements ShouldQueue
{
use Queueable;

/**
* Create a new job instance.
*/
public function __construct()
{
//
}

/**
* Execute the job.
*/
public function handle(): void
{
//
}
}
84 changes: 83 additions & 1 deletion app/Models/Site.php
Original file line number Diff line number Diff line change
@@ -1,10 +1,19 @@
<?php
<?php declare(strict_types=1);

namespace App\Models;

use App\Enum\HttpMethod;
use App\Exceptions\RemotesiteCommunicationException;
use GuzzleHttp\Client;
use GuzzleHttp\Exception\RequestException;
use GuzzleHttp\Psr7\Request;
use GuzzleHttp\Psr7\Response;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Illuminate\Support\Facades\App;
use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\ResponseInterface;

class Site extends Authenticatable
{
Expand Down Expand Up @@ -34,4 +43,77 @@ protected function casts(): array
'update_major' => 'bool'
];
}

public function getUrlAttribute(string $value): string
{
return rtrim($value, "/") . "/";
}


protected function performRequest(
RequestInterface $request,
array $options = []
): array {
/** @var Client $httpClient */
$httpClient = App::make(Client::class);

/** @var Response $response */
$response = $httpClient->send(
$request,
$options
);

// Validate response
if (!json_validate((string) $response->getBody())) {
throw new RequestException(
"Invalid JSON body",
$request,
$response
);
}

// Return decoded body
return json_decode(
(string) $response->getBody(),
true,
512,
JSON_THROW_ON_ERROR
);
}

public function performExtractionRequest(array $data, string $password): array
{
$request = new Request(
'POST',
$this->url . 'extract.php'
);

$data['password'] = $password;

return $this->performRequest(
$request,
[
'form_params' => $data,
'timeout' => 300.0
]
);
}

public function performWebserviceRequest(HttpMethod $method, string $endpoint, array $data = []): array
{
$request = new Request(
$method->name,
$this->url . $endpoint,
[
'Authorization' => 'JUpdate-Token ' . $this->key
]
);

return $this->performRequest(
$request,
[
"json" => $data
]
);
}
}
32 changes: 0 additions & 32 deletions app/Models/User.php

This file was deleted.

22 changes: 22 additions & 0 deletions app/Providers/HorizonServiceProvider.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?php

namespace App\Providers;

use Laravel\Horizon\Horizon;
use Laravel\Horizon\HorizonApplicationServiceProvider;

class HorizonServiceProvider extends HorizonApplicationServiceProvider
{
/**
* Overload authorization method from \Laravel\Horizon\HorizonApplicationServiceProvider
* to allow access to Horizon without having a logged in user.
*
* @return void
*/
protected function authorization()
{
Horizon::auth(function () {
return true;
});
}
}
4 changes: 3 additions & 1 deletion bootstrap/app.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@
health: '/up',
)
->withMiddleware(function (Middleware $middleware) {
//
$middleware->alias([
'horizonBasicAuth' => \App\Http\Middleware\HorizonBasicAuthMiddleware::class
]);
})
->withExceptions(function (Exceptions $exceptions) {
//
Expand Down
2 changes: 2 additions & 0 deletions bootstrap/providers.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,6 @@

return [
App\Providers\AppServiceProvider::class,
App\Providers\HorizonServiceProvider::class,
App\Providers\HttpclientServiceProvider::class,
];
9 changes: 0 additions & 9 deletions config/auth.php
Original file line number Diff line number Diff line change
Expand Up @@ -60,15 +60,6 @@
*/

'providers' => [
'users' => [
'driver' => 'eloquent',
'model' => env('AUTH_MODEL', App\Models\User::class),
],

// 'users' => [
// 'driver' => 'database',
// 'table' => 'users',
// ],
],

/*
Expand Down
Loading

0 comments on commit f50069a

Please sign in to comment.