pla-version/app/Http/Controllers/VersionController.php
Deon George 7e720b1970
All checks were successful
Create Docker Image / Build Docker Image (x86_64) (push) Successful in 30s
Create Docker Image / Build Docker Image (arm64) (push) Successful in 1m24s
Create Docker Image / Final Docker Image Manifest (push) Successful in 10s
Implement version table, update APIs when getting version info from github because the tags API was not retrieving our current git tags
2025-03-09 21:54:23 +11:00

162 lines
4.9 KiB
PHP

<?php
namespace App\Http\Controllers;
use GuzzleHttp\Client;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\{Cache,Log};
use Illuminate\Support\Str;
use App\Models\Site;
use App\Models\SiteVersion;
use App\Models\Version;
class VersionController extends Controller
{
private const CACHE_TIME = 86400; // Time to cache version
private const GH_URL = 'https://api.github.com/repos'; // GitHub URL
private const GH_PROJECT = 'leenooks/phpldapadmin';
private const GH_TREE = 'master';
private const VERSION_REGEX = '/^v([0-9]+\.[0-9]+\.[0-9]+(\.[0-9]+)?)-([a-z]{3})-([a-z0-9]{8})$/';
public function main(Request $request,?string $version=NULL) {
// Our version is in the format of either:
// v1.2.3-xxx-abcdef01
Log::info(sprintf('Connection from [%s] reporting version [%s]',$this->getUserIpAddr(),$version));
$matches = [];
if (preg_match(self::VERSION_REGEX,$version,$matches)) {
$so = Site::firstOrCreate([
'ip_address'=>$this->getUserIpAddr()
]);
$vo = Version::firstOrCreate(['version'=>$version]);
$sv = new SiteVersion;
$sv->version_id = $vo->id;
$so->versions()->save($sv);
// If xxx is "dev" we are a development version
switch($matches[3]) {
case 'dev':
$current = Cache::remember('dev',self::CACHE_TIME,function() {
$client = new Client;
$url = sprintf('%s/%s/commits/%s',self::GH_URL,self::GH_PROJECT,self::GH_TREE);
$response = $client->request('GET',$url,['form_params'=>['per_page'=>'1']]);
if ($response->getStatusCode() === 200) {
$result = collect(json_decode($response->getBody()));
return Str::limit($result->get('sha'),8,NULL);
}
return NULL;
});
if ($current) {
$repository = sprintf('v%s-dev-%s',$matches[1],$current);
// Find the tag associated with version $matches[1] and see if it is more recent than $matches[4]
$response = ($matches[4] === $current)
? ['action'=>'current','version'=>$repository]
: ['action'=>'upgrade','version'=>sprintf('v%s-%s-%s',$matches[1],$matches[3],$current)];
} else
$response = ['action'=>'unable','version'=>'vn.n.n-dev-hhhhhhhh'];
break;
case 'rel':
$current = Cache::remember('rel',self::CACHE_TIME,function() {
$client = new Client;
$url = sprintf('%s/%s/releases/latest',self::GH_URL,self::GH_PROJECT);
// Find the tag associated with version $matches[1] and see if there is a more recent version number
$response = $client->request('GET',$url);
if ($response->getStatusCode() === 200) {
$result = collect(json_decode($response->getBody()));
return $result;
}
return NULL;
});
if ($current) {
$repository = sprintf('v%s',$current->get('tag_name'));
$sha = $this->get_sha($current->get('tag_name'));
// If $matches[1] is smaller, "upgrade available"
if ($matches[1] < $current->get('tag_name'))
$response = ['action'=>'upgrade','version'=>$repository];
// If $matches[1] is the same, validate that $matches[4] is current and the same and if not, error
elseif ($matches[1] === $current->get('tag_name'))
$response = ($matches[4] === $sha) ? ['action'=>'current','version'=>$repository] : ['action'=>'mismatch','version'=>$repository];
// if $matches[1] is higher, abort
else
$response = ['action'=>'unknown','version'=>$repository];
} else
$response = ['action'=>'unable','version'=>'vn.n.n-rel-hhhhhhhh'];
break;
}
$sv->response = $response;
$sv->save();
return $response;
}
// Return the current version
return ['action'=>'invalid','version'=>'vn.n.n-xxxx-hhhhhhhh'];
}
private function get_sha(string $tag): ?string
{
return Cache::remember($tag,self::CACHE_TIME,function() use ($tag){
$url = sprintf('%s/%s/git/ref/tags/%s',self::GH_URL,self::GH_PROJECT,$tag);
// Find the tag associated with version $matches[1] and see if there is a more recent version number
$client = new Client;
$response = $client->request('GET',$url);
if ($response->getStatusCode() === 200) {
$result = collect(json_decode($response->getBody()));
return substr($result->get('object')->sha,0,8);
}
return NULL;
});
}
public function getUserIpAddr(): string
{
if (isset($_SERVER['HTTP_CLIENT_IP']))
$ipaddress = $_SERVER['HTTP_CLIENT_IP'];
else if(isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
$ips = preg_split('/,\s*/',$_SERVER['HTTP_X_FORWARDED_FOR']);
$ipaddress = $ips[0];
}
else if(isset($_SERVER['HTTP_X_FORWARDED']))
$ipaddress = $_SERVER['HTTP_X_FORWARDED'];
else if(isset($_SERVER['HTTP_FORWARDED_FOR']))
$ipaddress = $_SERVER['HTTP_FORWARDED_FOR'];
else if(isset($_SERVER['HTTP_FORWARDED']))
$ipaddress = $_SERVER['HTTP_FORWARDED'];
else if(isset($_SERVER['REMOTE_ADDR']))
$ipaddress = $_SERVER['REMOTE_ADDR'];
else
$ipaddress = 'UNKNOWN';
return $ipaddress;
}
}