cattr-app/server-application

View on GitHub
app/Http/Controllers/Api/AboutController.php

Summary

Maintainability
A
0 mins
Test Coverage
<?php

namespace App\Http\Controllers\Api;

use App\Console\Commands\RotateScreenshots;
use App\Helpers\ModuleHelper;
use App\Helpers\ReportHelper;
use App\Helpers\StorageCleaner;
use App\Helpers\Version;
use Artisan;
use Cache;
use Exception;
use GuzzleHttp\Client;
use Illuminate\Contracts\Container\BindingResolutionException;
use Illuminate\Http\JsonResponse;
use Illuminate\Routing\Controller;
use JsonException;
use Settings;

class AboutController extends Controller
{
    private Client $client;

    public function __construct()
    {
        $this->client = new Client([
            'base_uri' => config('app.stats_collector_url') . '/v2/',
            'headers' => ['x-cattr-instance' => Settings::scope('core')->get('instance')],
        ]);
    }

    public function reports(): JsonResponse
    {
        return responder()->success([
            'types' => ReportHelper::getAvailableReportFormats(),
        ])->respond();
    }

    /**
     * Returns information about this instance.
     * @throws JsonException
     */
    public function __invoke(): JsonResponse
    {
        $imageVersion = getenv('IMAGE_VERSION', true) ?: null;

        $releaseInfo = $this->requestReleaseInfo();
        $modulesInfo = $this->requestModulesInfo();
        $imageInfo = ($imageVersion) ? $this->requestImageInfo($imageVersion) : false;

        return responder()->success([
            'app' => [
                'version' => config('app.version'),
                'instance_id' => Settings::scope('core')->get('instance'),
                'vulnerable' => optional($releaseInfo)->vulnerable,
                'last_version' => optional($releaseInfo)->lastVersion,
                'message' => optional($releaseInfo)->flashMessage,
            ],
            'modules' => $modulesInfo,
            'image' => [
                'version' => $imageVersion,
                'vulnerable' => optional($imageInfo)->vulnerable,
                'last_version' => optional($imageInfo)->lastVersion,
                'message' => optional($imageInfo)->flashMessage,
            ]
        ])->respond();
    }

    private function requestReleaseInfo(): ?object
    {
        try {
            return json_decode(
                $this->client->get('release/' . config('app.version'))->getBody()->getContents(),
                false,
                512,
                JSON_THROW_ON_ERROR | JSON_THROW_ON_ERROR
            );
        } catch (Exception) {
            return null;
        }
    }

    /**
     * @throws JsonException
     */
    private function requestModulesInfo(): array
    {
        $options = [
            'json' => ModuleHelper::getModulesInfo(),
        ];

        try {
            return array_map(static function ($el) {
                $el['version'] = (string)(new Version($el['name']));

                return $el;
            }, json_decode(
                $this->client->post('modules', $options)->getBody()->getContents(),
                true,
                512,
                JSON_THROW_ON_ERROR | JSON_THROW_ON_ERROR
            )['modules']);
        } catch (Exception) {
            return ModuleHelper::getModulesInfo();
        }
    }

    private function requestImageInfo(string $imageVersion): ?object
    {
        try {
            return json_decode(
                $this->client->get("image/$imageVersion")->getBody()->getContents(),
                false,
                512,
                JSON_THROW_ON_ERROR | JSON_THROW_ON_ERROR
            );
        } catch (Exception) {
            return null;
        }
    }

    /**
     * @throws BindingResolutionException
     */
    public function storage(): JsonResponse
    {
        return responder()->success([
            'space' => [
                'left' => StorageCleaner::getFreeSpace(),
                'used' => StorageCleaner::getUsedSpace(),
                'total' => config('cleaner.total_space'),
            ],
            'threshold' => config('cleaner.threshold'),
            'need_thinning' => StorageCleaner::needThinning(),
            'screenshots_available' => StorageCleaner::countAvailableScreenshots(),
            'thinning' => [
                'now' => Cache::store('octane')->get('thinning_now'),
                'last' => Cache::store('octane')->get('last_thin'),
            ]
        ])->respond();
    }

    public function startStorageClean(): JsonResponse
    {
        Artisan::queue(RotateScreenshots::class);

        return responder()->success()->respond(204);
    }
}