restore: bring back f8a1310 (security review) state

Restores all files to the f8a1310 security-review snapshot as requested,
plus the 2 boot-critical fixes from a24c8a2 (config/session.php env()
instead of app()->environment(), and removal of the duplicate $activeTab
in ProjectMap.php) so the application actually boots.

Forward commit, no history rewrite. The 7d854ff state remains in history.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-17 10:36:44 +02:00
parent c44958ac16
commit 941dbd5997
26 changed files with 1163 additions and 1196 deletions
@@ -22,7 +22,7 @@
<input type="color" wire:model="layerColor" class="input input-bordered">
</div>
<div class="form-control">
<label class="label">{{ __('File') }} (GeoJSON, KML, Shapefile.zip, DWG)</label></br>
<label class="label">Archivo (GeoJSON, KML, Shapefile.zip, DWG)</label></br>
<input type="file" wire:model="uploadFile" class="file-input file-input-bordered">
@error('uploadFile') <span class="text-error">{{ $message }}</span> @enderror
</div>
@@ -49,13 +49,13 @@
</span>
</div>
<div>
<button wire:click="selectLayer({{ $layer->id }})" class="btn btn-xs btn-info">✏️ {{ __('Edit') }}</button>
<button wire:click="deleteLayer({{ $layer->id }})" wire:confirm="{{ __('Delete layer') }}?" class="btn btn-xs btn-error">🗑️</button>
<button wire:click="selectLayer({{ $layer->id }})" class="btn btn-xs btn-info">✏️ Editar</button>
<button wire:click="deleteLayer({{ $layer->id }})" class="btn btn-xs btn-error" onclick="return confirm('¿{{ __("Delete layer") }}?')">🗑️</button>
</div>
</div>
@endforeach
@if($layers->isEmpty())
<p class="text-center">{{ __("No layers. Create or import one.") }}</p>
<p class="text-center">{{ __("No results") }}. Crea una o importa.</p>
@endif
</div>
</div>
@@ -69,8 +69,8 @@
<h2 class="card-title">{{ __("Edit") }}</h2>
@if($selectedLayer)
<div class="mt-3 flex gap-2">
<button id="saveDrawingBtn" class="btn btn-primary">💾 {{ __('Save changes') }}</button>
<button wire:click="cancelEditing" class="btn btn-outline">{{ __('Cancel') }}</button>
<button id="saveDrawingBtn" class="btn btn-primary">💾 Guardar cambios</button>
<button wire:click="cancelEditing" class="btn btn-outline">Cancelar edición</button>
</div>
@endif
<div id="permanentMap" style="flex: 1; min-height: 500px; width: 100%; background: #e2e8f0;" wire:ignore></div>
@@ -88,6 +88,17 @@
let allLayersData = {}; // id -> {geojson, color}
let visibleLayerIds = [];
// XSS-safe HTML escaping for user-supplied data rendered in Leaflet popups
function escapeHtml(text) {
if (text === null || text === undefined) return '';
return String(text)
.replace(/&/g, '&amp;')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
.replace(/"/g, '&quot;')
.replace(/'/g, '&#039;');
}
// Inicialización del mapa
function initMap() {
if (map) return;
@@ -137,9 +148,9 @@
style: { color: data.color, weight: 3, opacity: 0.8, fillOpacity: 0.3 },
onEachFeature: (feature, layer) => {
const props = feature.properties;
const content = `<b>${props.name || 'Elemento'}</b><br>
Progreso: ${props.progress || 0}%<br>
Responsable: ${props.responsible || '-'}`;
const content = `<b>${escapeHtml(props.name) || 'Elemento'}</b><br>
Progreso: ${escapeHtml(props.progress) || 0}%<br>
Responsable: ${escapeHtml(props.responsible) || '-'}`;
layer.bindPopup(content);
}
}).addTo(displayGroup);
@@ -158,10 +169,10 @@
onEachFeature: (f, l) => {
l.feature = f;
const props = f.properties;
const content = `<b>${props.name || @js(__('Feature'))}</b><br>
@js(__('Progress')): ${props.progress || 0}%<br>
@js(__('Responsible')): ${props.responsible || '-'}<br>
<em>@js(__('Editable'))</em>`;
const content = `<b>${escapeHtml(props.name) || 'Elemento'}</b><br>
Progreso: ${escapeHtml(props.progress) || 0}%<br>
Responsable: ${escapeHtml(props.responsible) || '-'}<br>
<em>Editable</em>`;
l.bindPopup(content);
}
});