feat: add availableSharedVariables method and enhance env-var-input component for better password handling

This commit is contained in:
Andras Bacsai 2025-11-27 10:23:46 +01:00
parent e47e241da1
commit c2e1379ba8
4 changed files with 115 additions and 7 deletions

View File

@ -2,11 +2,14 @@
namespace App\Livewire\Project\Shared\EnvironmentVariable; namespace App\Livewire\Project\Shared\EnvironmentVariable;
use App\Models\Environment;
use App\Models\EnvironmentVariable as ModelsEnvironmentVariable; use App\Models\EnvironmentVariable as ModelsEnvironmentVariable;
use App\Models\Project;
use App\Models\SharedEnvironmentVariable; use App\Models\SharedEnvironmentVariable;
use App\Traits\EnvironmentVariableAnalyzer; use App\Traits\EnvironmentVariableAnalyzer;
use App\Traits\EnvironmentVariableProtection; use App\Traits\EnvironmentVariableProtection;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests; use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use Livewire\Attributes\Computed;
use Livewire\Component; use Livewire\Component;
class Show extends Component class Show extends Component
@ -193,6 +196,72 @@ class Show extends Component
} }
} }
#[Computed]
public function availableSharedVariables(): array
{
$team = currentTeam();
$result = [
'team' => [],
'project' => [],
'environment' => [],
];
// Early return if no team
if (! $team) {
return $result;
}
// Check if user can view team variables
try {
$this->authorize('view', $team);
$result['team'] = $team->environment_variables()
->pluck('key')
->toArray();
} catch (\Illuminate\Auth\Access\AuthorizationException $e) {
// User not authorized to view team variables
}
// Get project variables if we have a project_uuid in route
$projectUuid = data_get($this->parameters, 'project_uuid');
if ($projectUuid) {
$project = Project::where('team_id', $team->id)
->where('uuid', $projectUuid)
->first();
if ($project) {
try {
$this->authorize('view', $project);
$result['project'] = $project->environment_variables()
->pluck('key')
->toArray();
// Get environment variables if we have an environment_uuid in route
$environmentUuid = data_get($this->parameters, 'environment_uuid');
if ($environmentUuid) {
$environment = $project->environments()
->where('uuid', $environmentUuid)
->first();
if ($environment) {
try {
$this->authorize('view', $environment);
$result['environment'] = $environment->environment_variables()
->pluck('key')
->toArray();
} catch (\Illuminate\Auth\Access\AuthorizationException $e) {
// User not authorized to view environment variables
}
}
}
} catch (\Illuminate\Auth\Access\AuthorizationException $e) {
// User not authorized to view project variables
}
}
}
return $result;
}
public function delete() public function delete()
{ {
try { try {

View File

@ -26,6 +26,7 @@ class EnvVarInput extends Component
public bool $disabled = false, public bool $disabled = false,
public bool $readonly = false, public bool $readonly = false,
public ?string $helper = null, public ?string $helper = null,
public bool $allowToPeak = true,
public string $defaultClass = 'input', public string $defaultClass = 'input',
public string $autocomplete = 'off', public string $autocomplete = 'off',
public ?int $minlength = null, public ?int $minlength = null,
@ -72,6 +73,10 @@ class EnvVarInput extends Component
$this->name = $this->modelBinding !== 'null' ? $this->modelBinding : (string) $this->id; $this->name = $this->modelBinding !== 'null' ? $this->modelBinding : (string) $this->id;
} }
if ($this->type === 'password') {
$this->defaultClass = $this->defaultClass.' pr-[2.8rem]';
}
$this->scopeUrls = [ $this->scopeUrls = [
'team' => route('shared-variables.team.index'), 'team' => route('shared-variables.team.index'),
'project' => route('shared-variables.project.index'), 'project' => route('shared-variables.project.index'),

View File

@ -10,7 +10,8 @@
</label> </label>
@endif @endif
<div x-data="{ <div class="relative" x-data="{
type: '{{ $type }}',
showDropdown: false, showDropdown: false,
suggestions: [], suggestions: [],
selectedIndex: 0, selectedIndex: 0,
@ -181,8 +182,19 @@
} }
} }
}" }"
@click.outside="showDropdown = false" @click.outside="showDropdown = false">
class="relative">
@if ($type === 'password' && $allowToPeak)
<div x-on:click="changePasswordFieldType"
class="flex absolute inset-y-0 right-0 items-center pr-2 cursor-pointer dark:hover:text-white z-10">
<svg xmlns="http://www.w3.org/2000/svg" class="w-6 h-6" viewBox="0 0 24 24" stroke-width="1.5"
stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
<path d="M10 12a2 2 0 1 0 4 0a2 2 0 0 0 -4 0" />
<path d="M21 12c-2.4 4 -5.4 6 -9 6c-3.6 0 -6.6 -2 -9 -6c2.4 -4 5.4 -6 9 -6c3.6 0 6.6 2 9 6" />
</svg>
</div>
@endif
<input <input
x-ref="input" x-ref="input"
@ -198,7 +210,11 @@
wire:dirty.class="dark:border-l-warning border-l-coollabs border-l-4" wire:dirty.class="dark:border-l-warning border-l-coollabs border-l-4"
@endif @endif
wire:loading.attr="disabled" wire:loading.attr="disabled"
type="{{ $type }}" @if ($type === 'password')
:type="type"
@else
type="{{ $type }}"
@endif
@disabled($disabled) @disabled($disabled)
@if ($htmlId !== 'null') id="{{ $htmlId }}" @endif @if ($htmlId !== 'null') id="{{ $htmlId }}" @endif
name="{{ $name }}" name="{{ $name }}"

View File

@ -103,7 +103,13 @@
@if ($isDisabled) @if ($isDisabled)
<div class="flex flex-col w-full gap-2 lg:flex-row"> <div class="flex flex-col w-full gap-2 lg:flex-row">
<x-forms.input disabled id="key" /> <x-forms.input disabled id="key" />
<x-forms.input disabled type="password" id="value" /> <x-forms.env-var-input
disabled
type="password"
id="value"
:availableVars="$this->availableSharedVariables"
:projectUuid="data_get($parameters, 'project_uuid')"
:environmentUuid="data_get($parameters, 'environment_uuid')" />
@if ($is_shared) @if ($is_shared)
<x-forms.input disabled type="password" id="real_value" /> <x-forms.input disabled type="password" id="real_value" />
@endif @endif
@ -115,7 +121,13 @@
<x-forms.textarea :required="$is_redis_credential" type="password" id="value" /> <x-forms.textarea :required="$is_redis_credential" type="password" id="value" />
@else @else
<x-forms.input :disabled="$is_redis_credential" :required="$is_redis_credential" id="key" /> <x-forms.input :disabled="$is_redis_credential" :required="$is_redis_credential" id="key" />
<x-forms.input :required="$is_redis_credential" type="password" id="value" /> <x-forms.env-var-input
:required="$is_redis_credential"
type="password"
id="value"
:availableVars="$this->availableSharedVariables"
:projectUuid="data_get($parameters, 'project_uuid')"
:environmentUuid="data_get($parameters, 'environment_uuid')" />
@endif @endif
@if ($is_shared) @if ($is_shared)
<x-forms.input :disabled="$is_redis_credential" :required="$is_redis_credential" disabled type="password" id="real_value" /> <x-forms.input :disabled="$is_redis_credential" :required="$is_redis_credential" disabled type="password" id="real_value" />
@ -125,7 +137,13 @@
@else @else
<div class="flex flex-col w-full gap-2 lg:flex-row"> <div class="flex flex-col w-full gap-2 lg:flex-row">
<x-forms.input disabled id="key" /> <x-forms.input disabled id="key" />
<x-forms.input disabled type="password" id="value" /> <x-forms.env-var-input
disabled
type="password"
id="value"
:availableVars="$this->availableSharedVariables"
:projectUuid="data_get($parameters, 'project_uuid')"
:environmentUuid="data_get($parameters, 'environment_uuid')" />
@if ($is_shared) @if ($is_shared)
<x-forms.input disabled type="password" id="real_value" /> <x-forms.input disabled type="password" id="real_value" />
@endif @endif