Commit Graph

24 Commits

Author SHA1 Message Date
javier 3f240e5277 feat(issues): incidencias enriquecidas (tareas/comentarios/fotos/verificación) + tabla Rappasoft + logo
Web:
- IssueTask + IssueComment (modelos, migraciones, soft-deletes, campos de sync).
  Issue gana tasks()/comments() y accessor de % de avance derivado de tareas.
- IssueDetail (página): checklist con asignado/fecha límite/progreso, hilo de
  comentarios con foto por comentario, galería de fotos de la incidencia y flujo
  de verificación open→in_review→resolved/closed (+reabrir) con notas.
- Creación/edición en páginas propias (IssueForm), sin modal; al guardar redirige
  al detalle. Rutas projects.issues.create/edit/show.
- Listado con tabla Rappasoft (IssueTable): filtros por estado/prioridad, búsqueda,
  barra de progreso y acciones por fila gateadas por permisos; IssueManager queda
  como contenedor (cabecera + stats) que embebe la tabla.
- Seguridad: pertenencia al proyecto + permisos por acción (view/create/edit/delete
  issues, upload/delete media) en todos los componentes.

API móvil (offline):
- /sync: issue_task.create/update y issue_comment.create (idempotente, LWW).
- /media: parent_entity issue_task / issue_comment.
- bundle + tombstones incluyen issue_tasks / issue_comments.
- openapi.yaml + MOBILE_SYNC_PROTOCOL.md actualizados.

Tests: MobileApiTest 23 passing (+5); IssuesTablePageTest (3) smoke de la tabla.

Branding: logo RTE International — MAI Group (public/images/logo-rte.png) en login
y navegación; application-logo pasa de SVG por defecto a <img>.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 12:12:39 +02:00
javier 14758136b6 feat(api): mobile API Milestones 5+6 — media upload, sync_logs idempotency, OpenAPI
Milestone 5 (media):
- POST /api/v1/media — multipart upload, attaches to feature/issue/project/
  phase/layer, idempotent by uuid, authz member + 'upload media'. Added
  uuid+client_updated_at to media.
- Bundle now includes a 'media' array (URLs) for the project's project/feature/
  issue attachments (delta-aware).

Milestone 6 (hardening + docs):
- sync_logs table/model: every applied op is logged; /sync short-circuits on a
  repeated op uuid -> 'duplicate' (true idempotency for updates too, not just
  creates).
- Rate limiting on login (10/min), sync (60/min), media (120/min).
- docs/openapi.yaml: OpenAPI 3 contract for the mobile team.

Tests: 18 passing (added media upload idempotency + sync_logs idempotency).
The mobile API (Milestones 1-6) is now feature-complete on the webapp side.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 10:23:50 +02:00
javier b5deb1c53a feat(api): mobile API Milestone 3 — full PULL (delta, tombstones, templates)
ProjectApiController bundle now supports incremental sync:
- ?since=<ISO8601> returns only records changed after that time (phases, layers,
  features, inspections, issues, templates), each filtered by its own updated_at.
- 'deleted' tombstones (soft-deleted ids since 'since') for phases/layers/
  features/inspections/issues so the device can purge locally.
- Bundle now also includes inspections, issues and inspection templates
  (with version + content hash for incremental template download).
- New GET /api/v1/templates (accessible projects, ?since= delta).
Tests: 12 passing (added delta, tombstones, templates cases). Note: the 'since'
query param must be URL-encoded by clients (ISO8601 '+' offset).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 09:45:18 +02:00
javier 17a824f925 feat(api): mobile API Milestone 1+2 — Sanctum auth + offline sync vertical slice
Milestone 1 (auth foundation):
- Installed laravel/sanctum; HasApiTokens on User; published config + migration.
- routes/api.php with /api/v1; Sanctum 'ability' middleware alias registered.
- AuthController: POST login (long-lived revocable device token w/ ability
  mobile-sync + devices table), GET me, POST logout. New Device model/table.

Milestone 2 (vertical slice, offline-first):
- progress_updates: +uuid (client-generated) +client_updated_at.
- ProjectApiController: GET projects (accessibleBy), GET projects/{id}/bundle
  (project/phases/layers/features, membership-authorized).
- SyncController: POST sync — batch ops, idempotent by uuid, per-op result
  (applied/duplicate/error), server-set user_id, authz by permission+membership.
  Currently handles progress_update.create.

Tests: tests/Feature/Api/MobileApiTest (9 passing) — auth, accessible projects,
bundle authz, sync apply+idempotency, permission enforcement.

Also fixed a latent schema bug: projects.reference (and external_reference_1)
existed in the live DB but had no migration — added a guarded migration so fresh
installs match production.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 09:05:20 +02:00
javier 13f36e8ec0 feat(authz): per-route permission gating for /admin (granular admin roles)
Finishes Phase 2: the /admin route group no longer requires 'manage all'
globally. Each route is gated by its specific permission so a non-super-admin
role can be granted partial admin access:
- /admin/users (+show) -> can:view users; create -> can:create users;
  edit -> can:edit users
- /admin/roles, roles/*, permissions -> can:manage roles
- Aligned the role screens' mount checks (RoleForm/RoleView/RolePermissionManager)
  from 'manage all' to 'manage roles'.
- Nav 'Administrator' link now shows on can('view users').
Admins keep full access via Gate::before (manage all). Closure routes
(users/roles lists) are now protected at the route level.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-17 19:15:58 +02:00
javier 5587026446 feat(roles): Rappasoft list, slim create form, and 2-tab role view
1. Roles list now uses a Rappasoft table (RoleTable): search/sort, per-row
   view/edit/delete, and built-in bulk selection + 'Delete selected'. The
   /admin/roles page is a plain view embedding <livewire:role-table />.
   RoleForm create/edit now only has Name + Description (permissions removed).
2. New RoleView page (/admin/roles/{role}) with two tabs:
   - 'Details': header with role name + Back button; description with Edit/Delete
     buttons; table of users holding the role (avatar+name | last name | status).
   - 'Permissions': all permissions grouped by section (by resource), each with a
     toggle switch to grant/revoke for this role (Admin keeps 'manage all').
Removed the old RoleManager component/view (superseded).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-17 17:21:16 +02:00
javier 5092896a1e refactor(roles): role create/edit as a full page instead of a modal
Per feedback, 'New role' (and Edit) now open a dedicated page instead of a
modal:
- New RoleForm full-page component + view at /admin/roles/create and
  /admin/roles/{role}/edit (name, description, permission checkboxes; saves
  and redirects back to the list).
- RoleManager trimmed: the create/edit modal and its logic removed; 'New role'
  and the per-row/view-modal Edit are now links to the new pages.
- Kept the read-only View modal, single + bulk delete, and protections.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-17 17:05:01 +02:00
javier 938e704a67 feat(roles): role CRUD screen (list + form name/description + view/edit/delete + bulk)
Per request:
- Migration: add nullable 'description' to the roles table.
- RoleManager Livewire component + view at /admin/roles:
  * Roles list table with per-row checkboxes for bulk selection (+ select-all)
    and a 'Delete selected' bulk action (protected roles skipped).
  * 'New role' opens a modal form with just Name + Description (and permission
    checkboxes to assign).
  * Per-row View / Edit / Delete buttons (View modal shows description,
    counts and assigned permissions).
- Admin role stays protected (no rename/delete/lose 'manage all').
- /admin/users links to the new Roles screen; the phase-1 permission matrix
  stays available via a 'Matrix view' link.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-17 16:57:59 +02:00
javier 828e70fbe2 feat(permissions): admin role/permission matrix + Gate::before super-admin
Phase 1 (additive, doesn't touch existing checks):
- Gate::before grants everything to holders of 'manage all' (the Admin role),
  robustly (returns true/null, never false; swallows missing-permission).
- New RolePermissionManager Livewire component + view at /admin/permissions:
  editable Roles x Permissions matrix (toggle saves instantly), create/delete
  roles, create/delete permissions. Admin role and 'manage all' are protected.
- Link to the screen from /admin/users header.
Roles are editable from the UI as chosen.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-17 16:39:28 +02:00
javier 316e0ede39 fix(routes): remove dead /logout route + dead Auth controller imports
web.php referenced App\Http\Controllers\Auth\AuthenticatedSessionController
(and imported 8 other Auth\* controllers) that don't exist — this is a
Breeze+Volt app where auth is handled by Volt pages (routes/auth.php) and
logout by the Volt navigation action (App\Livewire\Actions\Logout).

The broken /logout route made 'php artisan route:list' throw
ReflectionException. Removed the dead route (nothing uses route('logout');
the nav uses wire:click=logout) and the unused Auth controller imports.
Login/register/reset already worked via Volt; logout works via the Volt action.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-17 15:38:28 +02:00
javier 564b433a62 style: manual UI tweaks (users/companies headers, wider layout, user-view, projects index)
User's manual changes: header slots with New-user/New-company actions, wider
max-w-7xl containers on /admin/users and /companies, plus tweaks to
user-view and projects index views. All views compile.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-17 15:33:02 +02:00
javier 6e66f707d5 restore: roll back to 7d854ff (stable pre-security state)
Full restore of the 7d854ff snapshot (2026-06-16 18:05, before the security
review). Forward commit, no history rewrite — f8a1310 and all later commits
remain recoverable in history.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-17 10:56:25 +02:00
javier 941dbd5997 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>
2026-06-17 10:36:44 +02:00
javier c44958ac16 revert: roll back to 7d854ff (pre-security-review state)
Restores all 27 files changed by the security commit (f8a1310) and later
work back to their 7d854ff state (2026-06-16 18:05), as requested. The
security rewrite regressed map functionality (tabs, inspection editor,
collapsing layers panel) without adding protections the 7d854ff version
did not already have (XSS escaping + IDOR checks were already present).

Done as a forward commit (no history rewrite / force-push) so f8a1310,
a24c8a2 and the merge remain in history and are fully recoverable.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-17 10:23:29 +02:00
javier f8a1310c0f security: fix 27 vulnerabilities + UI integration (Issues tab, project nav, validation)
Security fixes (27 vulnerabilities across 20 files):
CRITICAL:
- MediaManager: whitelist mediable types prevents RCE via class instantiation
- MediaManager/OfflineSyncController: IDOR fixes, remove Auth::id()??1 fallback
- ClientProjects: verify project ownership on all mutations (IDOR)
- CompanyManagement: Admin role check on mount() and mutations (auth bypass)
- ProjectMap: scope feature/template lookups to current project (IDOR x5)
- PhaseList/TemplateManager/LayerManager: scope mutations to owned resources (IDOR)
- ProjectEditTabs: Gate::authorize on mount() and updateProject()
- routes/web.php: reports routes moved inside can:manage all middleware (auth bypass)

MEDIUM:
- layer-manager: escapeHtml() on Leaflet popup interpolations (XSS)
- MediaManager: server-side MIME validation + 50MB limit
- ProjectList/ProjectUsers/ProjectCompanies/PhaseProgress: auth checks added
- AdminUsers/ReportsDashboard/ExportController: role/permission checks added

LOW:
- config/session.php: secure cookie tied to production env
- OfflineSyncController: sanitize storage path (path traversal)

UI integration:
- project-map: Issues tab (4th) with open-count badge
- project-map: project navigation bar (Dashboard/Map/Gantt/Report/Issues)
- project-dashboard: action buttons for Map/Gantt/Report/Issues
- project-form: validation error summary + per-field @error spans
- template-manager: validation error display

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-16 18:25:36 +02:00
javier 7d854ffb0a feat: i18n, language switcher fix, DataTable improvements, blade translations
- Translation system: lang/es/ PHP files (auth, validation, pagination, passwords)
- Rappasoft vendor translations published (lang/vendor/livewire-tables/es/)
- JSON files synced to 391 keys (EN + ES, full parity)
- APP_LOCALE changed to 'es', users.locale column default changed to 'es'
- Language switcher fixed: JS event + window.location.reload() avoids /livewire/update redirect
- SetLocale middleware fallback uses config('app.locale') instead of hardcoded 'en'
- setSortingPillsEnabled(false) on ProjectTable, CompanyTable, UserTable
- Translated 17 blade views: project-map, template-manager, layer-manager,
  company-management, phase-list, media-manager, reports-dashboard,
  client-projects, layer-upload, project-form, project-map-editor-tab,
  admin/users, projects/media, projects/templates, layouts/client
- Navigation 'Empresas' link uses __('Companies')
- Fixed typo key 'Fases and layers' -> 'Phases and layers'

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-16 18:05:53 +02:00
javier 0bf2d82ee1 Implement company management with logo, nickname, status fields; add filters by type and estado; CSV export functionality 2026-05-27 01:33:27 +02:00
javier c556a4910b feat: Add Excel export functionality for reports (projects, phases, inspections) using maatwebsite/excel 2026-05-25 17:21:25 +02:00
javier 8ca8dfbccc feat: Add client portal with project selection, progress overview, gallery, and change order approval 2026-05-25 15:57:06 +02:00
javier 4f5569a156 feat: Add reports dashboard with Chart.js analytics and PWA improvements (Avante) 2026-05-25 14:38:49 +02:00
javier 2cb10b0854 Gestión de usuarios por proyecto: ProjectUsers Livewire, AdminUsers, panel admin con roles, protección de rutas 2026-05-09 23:32:22 +02:00
javier 8f7b9aa09b Sistema de archivos multimedia: MediaManager, checkbox imágenes en mapa, modal visor, subida por feature/proyecto 2026-05-09 22:28:20 +02:00
javier 2a300241f9 Dashboard con stats, LayerUpload funcional, PhaseProgress eager-loading, README actualizado 2026-05-09 21:17:36 +02:00
javier 156aa14bbb Initial commit - construprogress app 2026-05-07 23:31:33 +02:00