Skip to content

Feature: foto de perfil para funcionarios y urlFoto en /auth/me

belen.varsi requested to merge pft/feature/foto-funcionario into dev

Qué se hizo

Los funcionarios ahora pueden tener foto de perfil, igual que los estudiantes, para cargarla desde "Mi perfil". Además, GET /auth/me devuelve la ruta de la foto propia, de estudiantes y de funcionarios, para que el frontend la muestre en la barra superior sin pedir el perfil aparte.

Por qué

La columna foto existía solo en la tabla estudiantes, así que un funcionario no tenía dónde guardar la suya. Y para mostrar la foto en la barra superior, el frontend tenía que hacer un pedido extra al perfil; ahora le alcanza con /auth/me, que ya pide al entrar.

Cambios

  • proyecto_schema.sql: columna foto VARCHAR(255) en funcionarios, con el constraint chk_funcionario_foto_extension (solo jpg/jpeg/png), igual que estudiantes.foto.
  • PUT /funcionarios/{id}/foto (nuevo, multipart, campo foto): lo puede usar el propio funcionario o alguien con EDITAR_FUNCIONARIO.
  • GET /funcionarios/{id}/foto (nuevo): el propio funcionario o alguien con VER_FUNCIONARIOS.
  • Mismas reglas que la foto de estudiante:
    • jpg/jpeg/png de hasta 5 MB;
    • no se borra el archivo anterior (criterio de "nunca borrado físico");
    • si falla el guardado en la base, se borra el archivo recién subido.
  • Las fotos van a la misma carpeta fotos/{id} que las de estudiantes. Los ids salen de la tabla usuarios, compartida entre estudiantes y funcionarios, así que nunca chocan.
  • urlFoto nuevo en FuncionarioResponseDTO y en GET /auth/me (/estudiantes/{id}/foto o /funcionarios/{id}/foto; null si no tiene foto).

Tests

  • FuncionarioServiceTest: subir foto (éxito, limpieza si falla el guardado, 404) y ver foto (éxito, sin foto cargada).
  • AuthServiceTest: urlFoto en /auth/me para funcionario y estudiante, con y sin foto.
  • FuncionarioMapperTest (nuevo): armado de urlFoto.
  • FuncionarioFotoSecurityTest (nuevo): reglas de @PreAuthorize con @EnableMethodSecurity real (el propio funcionario, otro sin permiso y otro con permiso).
  • ./mvnw test: pasan los 793 tests.

Cómo probar

  1. Aplicar la migración de abajo y levantar el backend.
  2. Como funcionario: PUT /funcionarios/{miId}/foto con un png → 200, y la respuesta trae urlFoto.
  3. GET /auth/me → trae urlFoto; GET /funcionarios/{miId}/foto → devuelve la imagen.
  4. Como funcionario sin permisos: subir o ver la foto de otro funcionario → 403.
  5. Subir un archivo .gif o de más de 5 MB → 400.

🗄️ Cambios en la base de datos: SÍ, obligatorios

Con ddl-auto=validate, el backend no arranca contra una base que no tenga la columna nueva. Cada uno tiene que correr esto una vez en su base local antes de levantar esta versión, y también hay que correrlo en el deploy:

ALTER TABLE proyecto.funcionarios ADD COLUMN IF NOT EXISTS foto VARCHAR(255);
ALTER TABLE proyecto.funcionarios ADD CONSTRAINT chk_funcionario_foto_extension
    CHECK (foto IS NULL OR foto ~* '\.(jpg|jpeg|png)$');

Con el contenedor de docker compose: guardar el SQL en un archivo y correr

docker exec -i sienep-db psql -U sienep -d sienep < migracion-foto-funcionario.sql

o pegarlo en pgAdmin. Quien cree la base desde cero con proyecto_schema.sql no tiene que hacer nada, porque ya está incluido.

✅ Probado: aplicado sobre el esquema actual de dev, la base queda idéntica a una creada desde cero con el esquema nuevo, y el backend arranca.

Compatibilidad

No choca con los otros MRs abiertos. Es independiente del MR de solicitudes de instancia: si se mergean los dos, hay que correr las dos migraciones, en cualquier orden.

Merge request reports

Loading