From 1bd6bdd296c6481fc61def20651dfeabf0b9a965 Mon Sep 17 00:00:00 2001 From: Davi Aliaga Date: Sat, 19 Sep 2026 02:36:54 -0300 Subject: [PATCH 1/7] =?UTF-8?q?feat/entity:=20adiciona=20campos=20fotoUrl?= =?UTF-8?q?=20e=20fotoPublicId=20=C3=A0=20entidade=20Usuario=20e=20aplica?= =?UTF-8?q?=20anota=C3=A7=C3=A3o=20DynamicInsert=20para=20ignorar=20coluna?= =?UTF-8?q?s=20nulas?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/br/com/acta/entity/core/Usuario.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/main/java/br/com/acta/entity/core/Usuario.java b/src/main/java/br/com/acta/entity/core/Usuario.java index d6e5457..a7c4a69 100644 --- a/src/main/java/br/com/acta/entity/core/Usuario.java +++ b/src/main/java/br/com/acta/entity/core/Usuario.java @@ -9,11 +9,13 @@ import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; +import org.hibernate.annotations.DynamicInsert; import java.util.Set; @Entity @Table(name = "usuario_sistema", schema = "public") +@DynamicInsert // ignora colunas nulas para aplicar default nas urls do cloudinary @Getter @Setter @NoArgsConstructor @@ -27,6 +29,12 @@ public class Usuario extends AuditoriaBase { @Column(name = "firebase_uid", unique = true, length = 128) private String firebaseUid; + @Column(name = "foto_url") + private String fotoUrl; + + @Column(name = "foto_public_id") + private String fotoPublicId; + @Column(name = "tipo_usuario", nullable = false) @Enumerated(EnumType.STRING) private TipoUsuario tipo; From e76fa3c09ec504f36e04feaeeb6724c65943d664 Mon Sep 17 00:00:00 2001 From: Davi Aliaga Date: Sat, 19 Sep 2026 02:37:35 -0300 Subject: [PATCH 2/7] =?UTF-8?q?feat/dto:=20adiciona=20campos=20fotoUrl=20e?= =?UTF-8?q?=20fotoPublicId=20=C3=A0=20resposta=20do=20usu=C3=A1rio=20e=20i?= =?UTF-8?q?gnora=20esses=20campos=20no=20mapeamento?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/br/com/acta/dto/core/usuario/UsuarioMapper.java | 4 ++++ .../java/br/com/acta/dto/core/usuario/UsuarioResponseDTO.java | 2 ++ 2 files changed, 6 insertions(+) diff --git a/src/main/java/br/com/acta/dto/core/usuario/UsuarioMapper.java b/src/main/java/br/com/acta/dto/core/usuario/UsuarioMapper.java index 104657d..8fdd6f9 100644 --- a/src/main/java/br/com/acta/dto/core/usuario/UsuarioMapper.java +++ b/src/main/java/br/com/acta/dto/core/usuario/UsuarioMapper.java @@ -20,6 +20,8 @@ public interface UsuarioMapper @Mapping(target = "ciclos", ignore = true) @Mapping(target = "metas", ignore = true) @Mapping(target = "empresa", ignore = true) + @Mapping(target = "fotoUrl", ignore = true) + @Mapping(target = "fotoPublicId", ignore = true) @Mapping(target = "id", ignore = true) @Mapping(target = "criadoEm", ignore = true) @Mapping(target = "atualizadoEm", ignore = true) @@ -32,6 +34,8 @@ public interface UsuarioMapper @Mapping(target = "ciclos", ignore = true) @Mapping(target = "metas", ignore = true) @Mapping(target = "empresa", ignore = true) + @Mapping(target = "fotoUrl", ignore = true) + @Mapping(target = "fotoPublicId", ignore = true) @Mapping(target = "id", ignore = true) @Mapping(target = "criadoEm", ignore = true) @Mapping(target = "atualizadoEm", ignore = true) diff --git a/src/main/java/br/com/acta/dto/core/usuario/UsuarioResponseDTO.java b/src/main/java/br/com/acta/dto/core/usuario/UsuarioResponseDTO.java index d5d42ca..b15ff28 100644 --- a/src/main/java/br/com/acta/dto/core/usuario/UsuarioResponseDTO.java +++ b/src/main/java/br/com/acta/dto/core/usuario/UsuarioResponseDTO.java @@ -11,6 +11,8 @@ public record UsuarioResponseDTO( TipoUsuario tipo, Long idEmpresa, StatusGeral status, + String fotoUrl, + String fotoPublicId, OffsetDateTime criadoEm, OffsetDateTime atualizadoEm ) { From dd60afb22444cb967191173549dc849410a06e08 Mon Sep 17 00:00:00 2001 From: Davi Aliaga Date: Sat, 19 Sep 2026 02:39:07 -0300 Subject: [PATCH 3/7] =?UTF-8?q?feat/controller:=20adiciona=20endpoint=20pa?= =?UTF-8?q?ra=20exclus=C3=A3o=20de=20foto=20do=20usu=C3=A1rio=20e=20atuali?= =?UTF-8?q?za=20servi=C3=A7o=20para=20gerenciar=20foto=20padr=C3=A3o?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../acta/controller/UsuarioController.java | 6 ++++ .../br/com/acta/service/UsuarioService.java | 29 +++++++++++++++++-- 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/src/main/java/br/com/acta/controller/UsuarioController.java b/src/main/java/br/com/acta/controller/UsuarioController.java index 78becac..7e83a1b 100644 --- a/src/main/java/br/com/acta/controller/UsuarioController.java +++ b/src/main/java/br/com/acta/controller/UsuarioController.java @@ -64,6 +64,12 @@ public ResponseEntity patch(@PathVariable @Positive Long id, return ResponseEntity.ok(usuario); } + @DeleteMapping("/{id}/foto") + public ResponseEntity excluirFoto(@PathVariable @Positive Long id) { + UsuarioResponseDTO usuario = service.excluirFoto(id); + return ResponseEntity.ok(usuario); + } + @DeleteMapping("/{id}") public ResponseEntity excluir(@PathVariable @Positive Long id) { service.excluir(id); diff --git a/src/main/java/br/com/acta/service/UsuarioService.java b/src/main/java/br/com/acta/service/UsuarioService.java index c9ce79d..d1422da 100644 --- a/src/main/java/br/com/acta/service/UsuarioService.java +++ b/src/main/java/br/com/acta/service/UsuarioService.java @@ -25,14 +25,16 @@ @Service public class UsuarioService extends BaseService { + private static final String FOTO_URL_PADRAO = "https://res.cloudinary.com/kcypohk3/image/upload/icone-de-perfil-de-avatar-padrao-imagem-de-usuario-de-midia-social-icone-de-avatar-cinza-silhueta-de-perfil-em-branco-ilustracao-vetorial_561158-3407"; + private static final String FOTO_PUBLIC_ID_PADRAO = "icone-de-perfil-de-avatar-padrao-imagem-de-usuario-de-midia-social-icone-de-avatar-cinza-silhueta-de-perfil-em-branco-ilustracao-vetorial_561158-3407"; private final EmpresaService empresaService; private final TarefaRepository tarefaRepo; private final MetaRepository metaRepo; private final UsuarioRepository repo; protected final UsuarioMapper mapper; private final PatchConfig patchConfig = new PatchConfig( - Set.of("nome", "email", "tipo", "idEmpresa"), - Set.of("nome", "email") + Set.of("nome", "email", "tipo", "idEmpresa", "fotoUrl"), + Set.of("nome", "email", "fotoUrl") ); public UsuarioService(EmpresaService empresaService, UsuarioRepository repo, UsuarioMapper mapper, TarefaRepository tarefaRepo, MetaRepository metaRepo, AuthService authService){ @@ -59,11 +61,34 @@ public UsuarioResponseDTO patch(Long id, Map campos) { if (repo.existsByEmailLoginIgnoreCase(email)) throw new UniqueViolationException("E-mail"); usuario.setEmailLogin(email); } + if (campos.containsKey("fotoUrl")) { + String fotoUrl = (String) campos.get("fotoUrl"); + usuario.setFotoUrl(fotoUrl); + usuario.setFotoPublicId( + fotoUrl.substring(fotoUrl.indexOf("/upload/") + 8) + .replaceFirst("^v\\d+/", "") + .replaceFirst("\\.[^.]+$", ""); + ); + } repo.save(usuario); return mapper.toResponse(usuario); } + @PreAuthorize("authService.isProprioUsuario(#id) or hasAnyRole('ADMIN', 'GESTOR')") + @Transactional + public UsuarioResponseDTO excluirFoto(Long id) { + configurarUsuarioAtual(); + + Usuario usuario = getEntity(id); + + usuario.setFotoUrl(FOTO_URL_PADRAO); + usuario.setFotoPublicId(FOTO_PUBLIC_ID_PADRAO); + + Usuario salvo = repo.save(usuario); + return mapper.toResponse(salvo); + } + @PreAuthorize("hasAnyRole('ADMIN', 'GESTOR') and authService.isUsuarioEmpresa(#idEmpresa)") public List buscar(Long idEmpresa, TipoUsuario tipo) { List usuarios; From b779e24f9cdc166fa43f002f6e996a2151fda18e Mon Sep 17 00:00:00 2001 From: Davi Aliaga Date: Sat, 19 Sep 2026 02:50:32 -0300 Subject: [PATCH 4/7] fix(service): corrige sintaxe ao atualizar foto do usuario --- src/main/java/br/com/acta/service/UsuarioService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/br/com/acta/service/UsuarioService.java b/src/main/java/br/com/acta/service/UsuarioService.java index d1422da..3c8f650 100644 --- a/src/main/java/br/com/acta/service/UsuarioService.java +++ b/src/main/java/br/com/acta/service/UsuarioService.java @@ -67,7 +67,7 @@ public UsuarioResponseDTO patch(Long id, Map campos) { usuario.setFotoPublicId( fotoUrl.substring(fotoUrl.indexOf("/upload/") + 8) .replaceFirst("^v\\d+/", "") - .replaceFirst("\\.[^.]+$", ""); + .replaceFirst("\\.[^.]+$", "") ); } From 5e0d1ecbefa411a283084f5d34cf313b668d4562 Mon Sep 17 00:00:00 2001 From: Davi Aliaga Date: Sat, 19 Sep 2026 02:59:34 -0300 Subject: [PATCH 5/7] =?UTF-8?q?feat/sql:=20adiciona=20campos=20foto=5Furl?= =?UTF-8?q?=20e=20foto=5Fpublic=5Fid=20=C3=A0=20tabela=20usuario=5Fsistema?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/resources/sql/script.sql | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/resources/sql/script.sql b/src/main/resources/sql/script.sql index 3a4263f..c0cf529 100644 --- a/src/main/resources/sql/script.sql +++ b/src/main/resources/sql/script.sql @@ -29,6 +29,8 @@ CREATE TABLE IF NOT EXISTS usuario_sistema ( status VARCHAR(40) NOT NULL CHECK (status IN ('ATIVO', 'INATIVO', 'PENDENTE', 'BLOQUEADO', 'ARQUIVADO')), criado_em TIMESTAMPTZ NOT NULL DEFAULT NOW(), atualizado_em TIMESTAMPTZ, + foto_url TEXT DEFAULT 'https://res.cloudinary.com/kcypohk3/image/upload/icone-de-perfil-de-avatar-padrao-imagem-de-usuario-de-midia-social-icone-de-avatar-cinza-silhueta-de-perfil-em-branco-ilustracao-vetorial_561158-3407', + foto_public_id TEXT DEFAULT 'icone-de-perfil-de-avatar-padrao-imagem-de-usuario-de-midia-social-icone-de-avatar-cinza-silhueta-de-perfil-em-branco-ilustracao-vetorial_561158-3407', CONSTRAINT ck_firebase_uid CHECK (status <> 'ATIVO' or firebase_uid IS NOT NULL) ); @@ -47,7 +49,7 @@ CREATE TABLE IF NOT EXISTS convite_usuario ( CONSTRAINT ck_data_expiracao CHECK (expira_em > criado_em), CONSTRAINT ck_convite_uso CHECK ((status = 'USADO' AND usado_em IS NOT NULL) OR (status <> 'USADO' AND usado_em IS NULL)) ); - + CREATE TABLE IF NOT EXISTS colaborador ( id BIGSERIAL PRIMARY KEY, id_empresa BIGINT NOT NULL REFERENCES empresa(id) ON DELETE CASCADE, @@ -442,4 +444,4 @@ CREATE TABLE IF NOT EXISTS pdca.anexo ( ) OR tipo_arquivo LIKE 'image/%' ) -); +); \ No newline at end of file From 9d96a86ee2e239ea3d5115e0a3db53d4d064a2ff Mon Sep 17 00:00:00 2001 From: Davi Aliaga Date: Sat, 19 Sep 2026 13:32:44 -0300 Subject: [PATCH 6/7] =?UTF-8?q?feat/cloudinary:=20atualiza=20URL=20e=20ID?= =?UTF-8?q?=20p=C3=BAblico=20do=20avatar=20default?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/br/com/acta/service/UsuarioService.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/br/com/acta/service/UsuarioService.java b/src/main/java/br/com/acta/service/UsuarioService.java index 3c8f650..dcbf6ee 100644 --- a/src/main/java/br/com/acta/service/UsuarioService.java +++ b/src/main/java/br/com/acta/service/UsuarioService.java @@ -25,8 +25,8 @@ @Service public class UsuarioService extends BaseService { - private static final String FOTO_URL_PADRAO = "https://res.cloudinary.com/kcypohk3/image/upload/icone-de-perfil-de-avatar-padrao-imagem-de-usuario-de-midia-social-icone-de-avatar-cinza-silhueta-de-perfil-em-branco-ilustracao-vetorial_561158-3407"; - private static final String FOTO_PUBLIC_ID_PADRAO = "icone-de-perfil-de-avatar-padrao-imagem-de-usuario-de-midia-social-icone-de-avatar-cinza-silhueta-de-perfil-em-branco-ilustracao-vetorial_561158-3407"; + private static final String FOTO_URL_PADRAO = "https://res.cloudinary.com/kcypohk3/image/upload/default-avatar"; + private static final String FOTO_PUBLIC_ID_PADRAO = "default-avatar"; private final EmpresaService empresaService; private final TarefaRepository tarefaRepo; private final MetaRepository metaRepo; From 2cf42b9c51d5ee7d8f3b05b958701748b8d9af01 Mon Sep 17 00:00:00 2001 From: davi aliaga Date: Sat, 19 Sep 2026 14:31:51 -0300 Subject: [PATCH 7/7] fix/cloudinary: Atualiza URL do avatar default --- src/main/resources/sql/script.sql | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/resources/sql/script.sql b/src/main/resources/sql/script.sql index c0cf529..0c7c7aa 100644 --- a/src/main/resources/sql/script.sql +++ b/src/main/resources/sql/script.sql @@ -29,8 +29,8 @@ CREATE TABLE IF NOT EXISTS usuario_sistema ( status VARCHAR(40) NOT NULL CHECK (status IN ('ATIVO', 'INATIVO', 'PENDENTE', 'BLOQUEADO', 'ARQUIVADO')), criado_em TIMESTAMPTZ NOT NULL DEFAULT NOW(), atualizado_em TIMESTAMPTZ, - foto_url TEXT DEFAULT 'https://res.cloudinary.com/kcypohk3/image/upload/icone-de-perfil-de-avatar-padrao-imagem-de-usuario-de-midia-social-icone-de-avatar-cinza-silhueta-de-perfil-em-branco-ilustracao-vetorial_561158-3407', - foto_public_id TEXT DEFAULT 'icone-de-perfil-de-avatar-padrao-imagem-de-usuario-de-midia-social-icone-de-avatar-cinza-silhueta-de-perfil-em-branco-ilustracao-vetorial_561158-3407', + foto_url TEXT DEFAULT 'https://res.cloudinary.com/kcypohk3/image/upload/default-avatar', + foto_public_id TEXT DEFAULT 'default-avatar', CONSTRAINT ck_firebase_uid CHECK (status <> 'ATIVO' or firebase_uid IS NOT NULL) ); @@ -444,4 +444,4 @@ CREATE TABLE IF NOT EXISTS pdca.anexo ( ) OR tipo_arquivo LIKE 'image/%' ) -); \ No newline at end of file +);