Két commit közötti fájlok összegyűjtését előkészítő felület első fázisa: célkörnyezet választás (e2e/d2d), commitlista, diff-előnézet figyelmeztetésekkel. Ez a fázis még semmit nem ír a fájlrendszerre, a csomagolás a phase2-ben érkezik. - DeploymentGuard: .env kapcsoló + hardkódolt stage whitelist + developer szerep + feature flag; a flag szándékosan nem biztonsági réteg, csak láthatóság-vezérlés - GitRepository: csak olvasó wrapper, argumentum-tömbös Symfony Process (nincs shell), hash- és referencia-validáció, core.quotePath=false az ékezetes útvonalakhoz - ChangeSetAnalyzer: kizárási lista, törlendő/másolandó szétválasztás (átnevezésnél mindkettő), figyelmeztetések migrációra, composer.lock-ra és a nem verziókövetett fordított assetekre Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
70 lines
2.4 KiB
PHP
70 lines
2.4 KiB
PHP
<?php
|
|
|
|
namespace App\Services\Deployment;
|
|
|
|
use App\Models\User;
|
|
use Laravel\Pennant\Feature;
|
|
|
|
/**
|
|
* A deployment csomagoló hozzáférés-ellenőrzése egy helyen.
|
|
*
|
|
* Az alkalmazás kódja manuális fájlmásolással kerül a szerverekre, tehát ez az oldal
|
|
* fizikailag ott lesz az éles környezetben is. Ezért négy, egymástól független feltétel
|
|
* van, és mindet MINDEN belépési ponton ellenőrizni kell (oldal mount, akciók, később a
|
|
* csomagoló service) - ha csak a felületet védjük, az látszatvédelem.
|
|
*
|
|
* A négyből a tényleges védelmet az .env kapcsoló és a stage whitelist adja, a
|
|
* jogosultságot a szerepkör. A feature flag NEM biztonsági réteg: a menü-láthatóságot
|
|
* vezérli, és lehetővé teszi a deploy nélküli kikapcsolást, illetve a név szerinti
|
|
* átadást (feature_flag_overrides) developer szerep osztogatása nélkül.
|
|
*/
|
|
class DeploymentGuard
|
|
{
|
|
public function isAllowed(?User $user = null): bool
|
|
{
|
|
return $this->denialReason($user) === null;
|
|
}
|
|
|
|
/**
|
|
* Az első nem teljesülő feltétel magyarázata, vagy null, ha minden rendben.
|
|
*/
|
|
public function denialReason(?User $user = null): ?string
|
|
{
|
|
if (! config('deployment.enabled')) {
|
|
return 'A deployment csomagoló ki van kapcsolva (DEPLOYMENT_PACKAGE_ENABLED).';
|
|
}
|
|
|
|
/** @var array<int, string> $stages */
|
|
$stages = (array) config('deployment.stages', []);
|
|
|
|
if (! in_array((string) config('app.stage'), $stages, true)) {
|
|
return sprintf(
|
|
'A deployment csomagoló csak fejlesztői környezetben használható (engedélyezett stage: %s, jelenlegi: %s).',
|
|
implode(', ', $stages),
|
|
(string) config('app.stage'),
|
|
);
|
|
}
|
|
|
|
if (! $user) {
|
|
return 'Bejelentkezés szükséges.';
|
|
}
|
|
|
|
if (! $user->hasRole((string) config('deployment.role'))) {
|
|
return 'A deployment csomagoló csak fejlesztői szerepkörrel érhető el.';
|
|
}
|
|
|
|
if (! Feature::for($user)->active((string) config('deployment.feature_flag'))) {
|
|
return 'A deployment csomagoló feature flag nincs bekapcsolva erre a felhasználóra.';
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
public function ensureAllowed(?User $user = null): void
|
|
{
|
|
if ($reason = $this->denialReason($user)) {
|
|
abort(403, $reason);
|
|
}
|
|
}
|
|
}
|