feat: lock environment variables

This commit is contained in:
Andras Bacsai 2023-10-24 15:41:21 +02:00
parent 6e73f7f2e4
commit 0232cf5b4c
6 changed files with 121 additions and 43 deletions

View File

@ -31,11 +31,17 @@ public function mount()
public function getDevView()
{
$this->variables = $this->resource->environment_variables->map(function ($item) {
if ($item->is_shown_once) {
return "$item->key=(locked secret)";
}
return "$item->key=$item->value";
})->sort()->join('
');
if ($this->showPreview) {
$this->variablesPreview = $this->resource->environment_variables_preview->map(function ($item) {
if ($item->is_shown_once) {
return "$item->key=(locked secret)";
}
return "$item->key=$item->value";
})->sort()->join('
');
@ -49,19 +55,27 @@ public function saveVariables($isPreview)
{
if ($isPreview) {
$variables = parseEnvFormatToArray($this->variablesPreview);
$existingVariables = $this->resource->environment_variables_preview();
$this->resource->environment_variables_preview()->delete();
} else {
$variables = parseEnvFormatToArray($this->variables);
$existingVariables = $this->resource->environment_variables();
$this->resource->environment_variables()->delete();
}
foreach ($variables as $key => $variable) {
$found = $existingVariables->where('key', $key)->first();
$found = $this->resource->environment_variables()->where('key', $key)->first();
$foundPreview = $this->resource->environment_variables_preview()->where('key', $key)->first();
if ($found) {
if ($found->is_shown_once) {
continue;
}
$found->value = $variable;
$found->save();
continue;
}
if ($foundPreview) {
if ($foundPreview->is_shown_once) {
continue;
}
$foundPreview->value = $variable;
$foundPreview->save();
continue;
} else {
$environment = new EnvironmentVariable();
$environment->key = $key;

View File

@ -5,7 +5,6 @@
use App\Models\EnvironmentVariable as ModelsEnvironmentVariable;
use Livewire\Component;
use Visus\Cuid2\Cuid2;
use Illuminate\Support\Str;
class Show extends Component
{
@ -13,29 +12,45 @@ class Show extends Component
public ModelsEnvironmentVariable $env;
public ?string $modalId = null;
public bool $isDisabled = false;
public bool $isLocked = false;
public string $type;
protected $rules = [
'env.key' => 'required|string',
'env.value' => 'nullable',
'env.is_build_time' => 'required|boolean',
'env.is_shown_once' => 'required|boolean',
];
protected $validationAttributes = [
'key' => 'key',
'value' => 'value',
'is_build_time' => 'build',
'key' => 'Key',
'value' => 'Value',
'is_build_time' => 'Build Time',
'is_shown_once' => 'Shown Once',
];
public function mount()
{
$this->isDisabled = false;
if (Str::of($this->env->key)->startsWith('SERVICE_FQDN') || Str::of($this->env->key)->startsWith('SERVICE_URL')) {
$this->isDisabled = true;
}
$this->modalId = new Cuid2(7);
$this->parameters = get_route_parameters();
$this->checkEnvs();
}
public function checkEnvs()
{
$this->isDisabled = false;
if (str($this->env->key)->startsWith('SERVICE_FQDN') || str($this->env->key)->startsWith('SERVICE_URL')) {
$this->isDisabled = true;
}
if ($this->env->is_shown_once) {
$this->isLocked = true;
}
}
public function lock()
{
$this->env->is_shown_once = true;
$this->env->save();
$this->checkEnvs();
$this->emit('refreshEnvs');
}
public function instantSave()
{
$this->submit();

View File

@ -11,7 +11,7 @@ class EnvironmentVariable extends Model
{
protected $guarded = [];
protected $casts = [
"key" => 'string',
'key' => 'string',
'value' => 'encrypted',
'is_build_time' => 'boolean',
];
@ -21,6 +21,10 @@ protected static function booted()
static::created(function ($environment_variable) {
if ($environment_variable->application_id && !$environment_variable->is_preview) {
$found = ModelsEnvironmentVariable::where('key', $environment_variable->key)->where('application_id', $environment_variable->application_id)->where('is_preview', true)->first();
$application = Application::find($environment_variable->application_id);
if ($application->build_pack === 'dockerfile') {
return;
}
if (!$found) {
ModelsEnvironmentVariable::create([
'key' => $environment_variable->key,
@ -33,7 +37,8 @@ protected static function booted()
}
});
}
public function service() {
public function service()
{
return $this->belongsTo(Service::class);
}
protected function value(): Attribute
@ -55,9 +60,9 @@ private function get_environment_variables(?string $environment_variable = null)
$variable = Str::after($environment_variable, 'global.');
$variable = Str::before($variable, '}}');
$variable = Str::of($variable)->trim()->value;
// $environment_variable = GlobalEnvironmentVariable::where('name', $environment_variable)->where('team_id', $team_id)->first()?->value;
ray('global env variable');
return $environment_variable;
// $environment_variable = GlobalEnvironmentVariable::where('name', $environment_variable)->where('team_id', $team_id)->first()?->value;
ray('global env variable');
return $environment_variable;
}
return $environment_variable;
}
@ -77,5 +82,4 @@ protected function key(): Attribute
set: fn (string $value) => Str::of($value)->trim(),
);
}
}

View File

@ -0,0 +1,28 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('environment_variables', function (Blueprint $table) {
$table->boolean('is_shown_once')->default(false);
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('environment_variables', function (Blueprint $table) {
$table->dropColumn('is_shown_once');
});
}
};

View File

@ -28,8 +28,7 @@
@endif
@else
<form wire:submit.prevent='saveVariables(false)' class="flex flex-col gap-2">
<x-forms.textarea rows=25 class="whitespace-pre-wrap"
id="variables"></x-forms.textarea>
<x-forms.textarea rows=25 class="whitespace-pre-wrap" id="variables"></x-forms.textarea>
<x-forms.button type="submit" class="btn btn-primary">Save</x-forms.button>
</form>
@if ($showPreview)

View File

@ -6,36 +6,54 @@ class="font-bold text-warning">({{ $env->key }})</span>?</p>
</x-slot:modalBody>
</x-modal>
<form wire:submit.prevent='submit' class="flex flex-col items-center gap-2 xl:flex-row">
@if ($isDisabled)
@if ($isLocked)
<svg class="icon" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<g fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2">
<path d="M5 13a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2v6a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2v-6z" />
<path d="M11 16a1 1 0 1 0 2 0a1 1 0 0 0-2 0m-3-5V7a4 4 0 1 1 8 0v4" />
</g>
</svg>
<x-forms.input disabled id="env.key" />
<x-forms.input disabled type="password" id="env.value" />
@if ($type !== 'service')
<x-forms.checkbox instantSave id="env.is_build_time" label="Build Variable?" />
@endif
@else
<x-forms.input id="env.key" />
<x-forms.input type="password" id="env.value" />
@if ($type !== 'service')
<x-forms.checkbox instantSave id="env.is_build_time" label="Build Variable?" />
@if ($isDisabled)
<x-forms.input disabled id="env.key" />
<x-forms.input disabled type="password" id="env.value" />
@if ($type !== 'service')
<x-forms.checkbox instantSave id="env.is_build_time" label="Build Variable?" />
@endif
@else
<x-forms.input id="env.key" />
<x-forms.input type="password" id="env.value" />
@if ($type !== 'service')
<x-forms.checkbox instantSave id="env.is_build_time" label="Build Variable?" />
@endif
@endif
@endif
<div class="flex gap-2">
@if ($isDisabled)
<x-forms.button disabled type="submit">
Update
</x-forms.button>
<x-forms.button disabled isError isModal modalId="{{ $modalId }}">
Delete
</x-forms.button>
@else
<x-forms.button type="submit">
Update
</x-forms.button>
@if ($isLocked)
<x-forms.button isError isModal modalId="{{ $modalId }}">
Delete
</x-forms.button>
@else
@if ($isDisabled)
<x-forms.button disabled type="submit">
Update
</x-forms.button>
<x-forms.button disabled isError isModal modalId="{{ $modalId }}">
Delete
</x-forms.button>
@else
<x-forms.button type="submit">
Update
</x-forms.button>
<x-forms.button wire:click='lock'>
Lock
</x-forms.button>
<x-forms.button isError isModal modalId="{{ $modalId }}">
Delete
</x-forms.button>
@endif
@endif
</div>
</form>
</div>