diff --git a/.gitignore b/.gitignore
index 549e00a..3b5258c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,8 +1,10 @@
HELP.md
+pdf/
target/
!.mvn/wrapper/maven-wrapper.jar
!**/src/main/**/target/
!**/src/test/**/target/
+htmlReport
### STS ###
.apt_generated
diff --git a/mvnw.cmd b/mvnw.cmd
index 95ba6f5..ed2c040 100644
--- a/mvnw.cmd
+++ b/mvnw.cmd
@@ -1,10 +1,10 @@
@REM ----------------------------------------------------------------------------
@REM Licensed to the Apache Software Foundation (ASF) under one
-@REM or more contributor license agreements. See the NOTICE file
+@REM or more contributor license agreements. See the NOTICE fileEntity
@REM distributed with this work for additional information
-@REM regarding copyright ownership. The ASF licenses this file
+@REM regarding copyright ownership. The ASF licenses this fileEntity
@REM to you under the Apache License, Version 2.0 (the
-@REM "License"); you may not use this file except in compliance
+@REM "License"); you may not use this fileEntity except in compliance
@REM with the License. You may obtain a copy of the License at
@REM
@REM https://www.apache.org/licenses/LICENSE-2.0
@@ -153,7 +153,7 @@ if exist %WRAPPER_JAR% (
)
@REM End of extension
-@REM If specified, validate the SHA-256 sum of the Maven wrapper jar file
+@REM If specified, validate the SHA-256 sum of the Maven wrapper jar fileEntity
SET WRAPPER_SHA_256_SUM=""
FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
IF "%%A"=="wrapperSha256Sum" SET WRAPPER_SHA_256_SUM=%%B
diff --git a/pom.xml b/pom.xml
index 882861c..3d4bc8c 100644
--- a/pom.xml
+++ b/pom.xml
@@ -15,6 +15,7 @@
sempre-alerta
17
+ 2.3.0
@@ -37,11 +38,34 @@
org.springframework.boot
spring-boot-starter-web
+
+ org.springframework.boot
+ spring-boot-starter-security
+
+
+ org.springframework.security
+ spring-security-test
+ test
+
+
+ org.springdoc
+ springdoc-openapi-starter-webmvc-ui
+ ${springdoc-openapi-starter-webmvc-ui.version}
+
+
+ org.springdoc
+ springdoc-openapi-starter-webmvc-api
+ ${springdoc-openapi-starter-webmvc-ui.version}
+
org.flywaydb
flyway-core
-
+
+ com.h2database
+ h2
+ test
+
org.postgresql
postgresql
@@ -52,6 +76,23 @@
lombok
true
+
+
+ com.github.slugify
+ slugify
+ 3.0.6
+
+
+ com.github.javafaker
+ javafaker
+ 1.0.2
+ test
+
+
+ com.auth0
+ java-jwt
+ 4.4.0
+
org.springframework.boot
spring-boot-starter-test
@@ -93,6 +134,10 @@
lombok
+
+ matheusvict/${project.artifactId}:${project.version}
+
+ IF_NOT_PRESENT
diff --git a/src/main/java/com/institutosemprealerta/semprealerta/SempreAlertaApplication.java b/src/main/java/com/institutosemprealerta/semprealerta/SempreAlertaApplication.java
index 3c8af65..1efe528 100644
--- a/src/main/java/com/institutosemprealerta/semprealerta/SempreAlertaApplication.java
+++ b/src/main/java/com/institutosemprealerta/semprealerta/SempreAlertaApplication.java
@@ -1,9 +1,12 @@
package com.institutosemprealerta.semprealerta;
+import io.swagger.v3.oas.annotations.OpenAPIDefinition;
+import io.swagger.v3.oas.annotations.servers.Server;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
+@OpenAPIDefinition(servers = {@Server(url = "/", description = "Default server url")})
public class SempreAlertaApplication {
public static void main(String[] args) {
diff --git a/src/main/java/com/institutosemprealerta/semprealerta/application/controllers/AuthenticationController.java b/src/main/java/com/institutosemprealerta/semprealerta/application/controllers/AuthenticationController.java
new file mode 100644
index 0000000..693df89
--- /dev/null
+++ b/src/main/java/com/institutosemprealerta/semprealerta/application/controllers/AuthenticationController.java
@@ -0,0 +1,33 @@
+package com.institutosemprealerta.semprealerta.application.controllers;
+
+import com.institutosemprealerta.semprealerta.domain.ports.out.request.LoginDTO;
+import com.institutosemprealerta.semprealerta.domain.ports.out.responses.LoginResponse;
+import com.institutosemprealerta.semprealerta.domain.service.AuthenticationService;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.validation.Valid;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+@RestController
+@RequestMapping("/auth")
+@Tag(name = "auth")
+public class AuthenticationController {
+
+ private final AuthenticationService authenticationService;
+
+ public AuthenticationController(AuthenticationService authenticationService) {
+ this.authenticationService = authenticationService;
+ }
+
+ @PostMapping("/login")
+ @Operation(summary = "Login", description = "You can login with your email and password")
+
+ public ResponseEntity> login(@RequestBody @Valid LoginDTO loginRequestBody) {
+ LoginResponse token = authenticationService.login(loginRequestBody);
+ return ResponseEntity.ok(token);
+ }
+}
diff --git a/src/main/java/com/institutosemprealerta/semprealerta/application/controllers/FilesStorageController.java b/src/main/java/com/institutosemprealerta/semprealerta/application/controllers/FilesStorageController.java
new file mode 100644
index 0000000..8dffd37
--- /dev/null
+++ b/src/main/java/com/institutosemprealerta/semprealerta/application/controllers/FilesStorageController.java
@@ -0,0 +1,89 @@
+package com.institutosemprealerta.semprealerta.application.controllers;
+
+import com.institutosemprealerta.semprealerta.domain.service.StorageService;
+import com.institutosemprealerta.semprealerta.domain.ports.out.responses.FileResponse;
+import com.institutosemprealerta.semprealerta.swagger.annotations.BadRequestResponse;
+import com.institutosemprealerta.semprealerta.swagger.annotations.CreatedResponse;
+import com.institutosemprealerta.semprealerta.swagger.annotations.NotFoundResponse;
+import com.institutosemprealerta.semprealerta.swagger.annotations.OkResponse;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.servlet.http.HttpServletRequest;
+import org.springframework.core.io.Resource;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
+import org.springframework.web.servlet.support.ServletUriComponentsBuilder;
+
+import java.io.IOException;
+import java.net.URI;
+import java.util.List;
+
+@Controller
+@RequestMapping("/api/v1/files")
+@Tag(name = "Files", description = "Files management")
+public class FilesStorageController {
+ private StorageService storageService;
+
+ public FilesStorageController(StorageService storageService) {
+ this.storageService = storageService;
+ }
+
+ @Operation(summary = "Faça o upload de um arquivo", description = "Upload de um arquivo para o servidor")
+ @PostMapping(value = "/upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
+ @CreatedResponse
+ @BadRequestResponse
+ public ResponseEntity uploadFile(@RequestPart("file") MultipartFile file, @RequestParam("file_type") String fileType) {
+
+ String fileName = storageService.store(file, fileType);
+
+ String fileDownloadUri = ServletUriComponentsBuilder.fromCurrentContextPath()
+ .path("/api/v1/files/download/")
+ .path(fileName)
+ .toUriString();
+
+ URI uri = URI.create(fileDownloadUri);
+ return ResponseEntity.created(uri).body("File uploaded successfully, file name: " + fileName + " on path: " + fileDownloadUri);
+ }
+
+ @GetMapping("/download/{fileName:.+}")
+ @ResponseBody
+ @Operation(summary = "Download de um arquivo", description = "Baixe um arquivo pelo nome do arquivo")
+ @OkResponse
+ @NotFoundResponse
+ @BadRequestResponse
+ public ResponseEntity downloadFile(
+ @PathVariable String fileName,
+ HttpServletRequest request
+ ) {
+
+ try {
+ Resource resource = storageService.loadAsResource(fileName);
+ String contentType = request.getServletContext().getMimeType(resource.getFile().getAbsolutePath());
+
+ if (contentType == null) {
+ contentType = MediaType.APPLICATION_OCTET_STREAM.getType();
+ }
+
+ return ResponseEntity.ok()
+ .contentType(MediaType.parseMediaType(contentType))
+ .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + resource.getFilename() + "\"")
+ .body(resource);
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @GetMapping("/list")
+ @Operation(summary = "List todos os arquivos", description = "Liste todos os arquivos do servidor")
+ @OkResponse
+ @BadRequestResponse
+ public ResponseEntity> listFiles() throws IOException {
+ List fileNames = storageService.loadAll();
+
+ return ResponseEntity.ok(fileNames);
+ }
+}
diff --git a/src/main/java/com/institutosemprealerta/semprealerta/application/controllers/PostController.java b/src/main/java/com/institutosemprealerta/semprealerta/application/controllers/PostController.java
new file mode 100644
index 0000000..7be3df5
--- /dev/null
+++ b/src/main/java/com/institutosemprealerta/semprealerta/application/controllers/PostController.java
@@ -0,0 +1,68 @@
+package com.institutosemprealerta.semprealerta.application.controllers;
+
+import com.institutosemprealerta.semprealerta.domain.service.PostService;
+import com.institutosemprealerta.semprealerta.domain.model.Post;
+import com.institutosemprealerta.semprealerta.swagger.annotations.*;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.validation.Valid;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.Pageable;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.*;
+
+import java.net.URI;
+
+@RestController
+@RequestMapping("api/v1/posts")
+@Tag(name = "Post", description = "Post management")
+public class PostController {
+ private final PostService postService;
+
+ public PostController(PostService postService) {
+ this.postService = postService;
+ }
+
+ @GetMapping
+ @Operation(summary = "Lista de todos os posts", description = "Lista de todos os posts com paginação")
+ @OkResponse
+ public ResponseEntity> getAllPosts(Pageable pageable) {
+ return ResponseEntity.ok(postService.listAll(pageable));
+ }
+
+ @PostMapping
+ @Operation(summary = "Criar postagem", description = "Crie uma nova postagem")
+ @CreatedResponse
+ @BadRequestResponse
+ public ResponseEntity> createPost(@Valid @RequestBody Post post) {
+ String slug = postService.save(post);
+ return ResponseEntity.created(URI.create("/api/v1/posts/" + slug)).build();
+ }
+
+ @GetMapping("/{slug}")
+ @Operation(summary = "Pegar post pelo slug", description = "Procura um post pelo seu slug")
+ @OkResponse
+ @NotFoundResponse
+ public ResponseEntity getPostBySlug(@PathVariable String slug) {
+ return ResponseEntity.ok(postService.findBySlug(slug));
+ }
+
+ @PutMapping("/{id}")
+ @Operation(summary = "Atualizar post", description = "Atualize um post existente pelo seu id")
+ @NoContentResponse
+ @NotFoundResponse
+ @BadRequestResponse
+ public ResponseEntity> updatePost(@PathVariable Long id, @Valid @RequestBody Post post) {
+ postService.update(id, post);
+ return ResponseEntity.noContent().build();
+ }
+
+ @DeleteMapping("/{id}")
+ @Operation(summary = "Deletar post", description = "Deleta um post existente pelo seu id")
+ @NoContentResponse
+ @NotFoundResponse
+ public ResponseEntity> deletePost(@PathVariable Long id) {
+ postService.delete(id);
+ return ResponseEntity.noContent().build();
+ }
+}
diff --git a/src/main/java/com/institutosemprealerta/semprealerta/application/controllers/UserController.java b/src/main/java/com/institutosemprealerta/semprealerta/application/controllers/UserController.java
new file mode 100644
index 0000000..a98fa57
--- /dev/null
+++ b/src/main/java/com/institutosemprealerta/semprealerta/application/controllers/UserController.java
@@ -0,0 +1,71 @@
+package com.institutosemprealerta.semprealerta.application.controllers;
+
+import com.institutosemprealerta.semprealerta.domain.service.UserService;
+import com.institutosemprealerta.semprealerta.domain.model.UserDTO;
+import com.institutosemprealerta.semprealerta.domain.ports.out.responses.UserResponse;
+import com.institutosemprealerta.semprealerta.infrastructure.entity.user.User;
+import com.institutosemprealerta.semprealerta.swagger.annotations.*;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.validation.Valid;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.*;
+
+@RestController
+@RequestMapping("api/v1/user")
+@Tag(name = "User", description = "Administração de usuários")
+public class UserController {
+
+ private final UserService userService;
+
+ public UserController(UserService userService) {
+ this.userService = userService;
+ }
+
+ @PostMapping
+ @Operation(summary = "Criação de um usuário", description = "Criação de um usuário no sistema")
+ @CreatedResponse
+ @ConflictResponse
+ public ResponseEntity> createUser(@Valid @RequestBody UserDTO user) {
+ userService.save(user.toDomain());
+ return ResponseEntity.status(HttpStatus.CREATED).build();
+ }
+
+ @GetMapping("/{id}")
+ @Operation(summary = "Busca de um usuário", description = "Busca de um usuário pelo id")
+ @OkResponse
+ @NotFoundResponse
+ public ResponseEntity findById(@PathVariable int id) {
+ User userFound = userService.findById(id);
+ return ResponseEntity.ok().body(UserResponse.toResponse(userFound));
+ }
+
+ @GetMapping("/registration/{reg}")
+ @Operation(summary = "Busca de um usuário", description = "Busca de um usuário pela matrícula")
+ @OkResponse
+ @NotFoundResponse
+ public ResponseEntity findByRegistration(@PathVariable String reg) {
+ User userFound = userService.findByRegistration(reg);
+ return ResponseEntity.ok().body(UserResponse.toResponse(userFound));
+ }
+
+ @PutMapping("/{id}")
+ @Operation(summary = "Atualização de um usuário", description = "Atualização de um usuário pelo id")
+ @NoContentResponse
+ @NotFoundResponse
+ @ConflictResponse
+ public ResponseEntity> updateUser(@PathVariable int id, @RequestBody UserDTO user) {
+ userService.update(id, user.toDomain());
+ return ResponseEntity.noContent().build();
+ }
+
+ @DeleteMapping("/{id}")
+ @Operation(summary = "Deleção de um usuário", description = "Deleção de um usuário pelo id")
+ @NoContentResponse
+ @NotFoundResponse
+ public ResponseEntity> deleteUser(@PathVariable int id) {
+ userService.delete(id);
+ return ResponseEntity.status(HttpStatus.NO_CONTENT).build();
+ }
+}
diff --git a/src/main/java/com/institutosemprealerta/semprealerta/application/handler/GlobalExceptionHandler.java b/src/main/java/com/institutosemprealerta/semprealerta/application/handler/GlobalExceptionHandler.java
new file mode 100644
index 0000000..1361ba7
--- /dev/null
+++ b/src/main/java/com/institutosemprealerta/semprealerta/application/handler/GlobalExceptionHandler.java
@@ -0,0 +1,118 @@
+package com.institutosemprealerta.semprealerta.application.handler;
+
+import com.institutosemprealerta.semprealerta.domain.ports.out.exceptions.ExceptionPattern;
+import com.institutosemprealerta.semprealerta.domain.ports.out.exceptions.file.FileNotFoundException;
+import com.institutosemprealerta.semprealerta.domain.ports.out.exceptions.file.InvalidFileException;
+import com.institutosemprealerta.semprealerta.domain.ports.out.exceptions.post.PostNotFoundException;
+import com.institutosemprealerta.semprealerta.domain.ports.out.exceptions.user.EmailAlreadyExistsException;
+import com.institutosemprealerta.semprealerta.domain.ports.out.exceptions.user.UserNotFoundException;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.validation.FieldError;
+import org.springframework.web.bind.MethodArgumentNotValidException;
+import org.springframework.web.bind.annotation.ControllerAdvice;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+
+import java.time.LocalDateTime;
+import java.util.List;
+import java.util.stream.Collectors;
+
+@ControllerAdvice
+public class GlobalExceptionHandler {
+
+ @ExceptionHandler(UserNotFoundException.class)
+ public ResponseEntity handlerUserNotFoundException(UserNotFoundException exception) {
+ LocalDateTime timestamp = LocalDateTime.now();
+ return ResponseEntity.status(HttpStatus.NOT_FOUND).body(
+ ExceptionPattern.builder()
+ .title("User Not Found Exception")
+ .status(HttpStatus.NOT_FOUND.value())
+ .details(exception.getMessage())
+ .timestamp(timestamp)
+ .developerMessage(exception.getClass().getName())
+ .build()
+ );
+ }
+
+ @ExceptionHandler(EmailAlreadyExistsException.class)
+ public ResponseEntity handlerEmailAlreadyExistsException(EmailAlreadyExistsException bre) {
+ LocalDateTime timestamp = LocalDateTime.now();
+
+ return ResponseEntity.status(HttpStatus.CONFLICT).body(
+ ExceptionPattern.builder()
+ .title("Email already exists, check the documentation")
+ .status(HttpStatus.CONFLICT.value())
+ .details(bre.getMessage())
+ .timestamp(timestamp)
+ .developerMessage(bre.getClass().getName())
+ .build()
+ );
+ }
+
+ @ExceptionHandler(PostNotFoundException.class)
+ public ResponseEntity handlerPostNotFoundException(PostNotFoundException bre) {
+ LocalDateTime timestamp = LocalDateTime.now();
+
+ return ResponseEntity.status(HttpStatus.NOT_FOUND).body(
+ ExceptionPattern.builder()
+ .title("Post not found, check the documentation")
+ .status(HttpStatus.NOT_FOUND.value())
+ .details(bre.getMessage())
+ .timestamp(timestamp)
+ .developerMessage(bre.getClass().getName())
+ .build()
+ );
+ }
+
+ @ExceptionHandler(FileNotFoundException.class)
+ public ResponseEntity handlerFileNotFoundException(FileNotFoundException bre) {
+ LocalDateTime timestamp = LocalDateTime.now();
+
+ return ResponseEntity.status(HttpStatus.NOT_FOUND).body(
+ ExceptionPattern.builder()
+ .title("File not found, check the documentation")
+ .status(HttpStatus.NOT_FOUND.value())
+ .details(bre.getMessage())
+ .timestamp(timestamp)
+ .developerMessage(bre.getClass().getName())
+ .build()
+ );
+ }
+
+ @ExceptionHandler(InvalidFileException.class)
+ public ResponseEntity handlerInvalidFileException(InvalidFileException bre) {
+ LocalDateTime timestamp = LocalDateTime.now();
+
+ return ResponseEntity.badRequest().body(
+ ExceptionPattern.builder()
+ .title("The file is invalid, check the documentation or try another file type")
+ .status(HttpStatus.BAD_REQUEST.value())
+ .details(bre.getMessage())
+ .timestamp(timestamp)
+ .developerMessage(bre.getClass().getName())
+ .build()
+ );
+ }
+
+
+ @ExceptionHandler(MethodArgumentNotValidException.class)
+ public ResponseEntity handlerMethodArgumentNotValidExceptionException(MethodArgumentNotValidException exception) {
+ List fieldError = exception.getBindingResult().getFieldErrors();
+
+ String fields = fieldError.stream().map(FieldError::getField).collect(Collectors.joining(", "));
+ String fieldMessage = fieldError.stream().map(FieldError::getDefaultMessage).collect(Collectors.joining(", "));
+ LocalDateTime timestamp = LocalDateTime.now();
+
+ return ResponseEntity.badRequest().body(
+ ExceptionPattern.builder()
+ .title("Bad Request Exception, Invalid Fields")
+ .status(HttpStatus.BAD_REQUEST.value())
+ .details("Check the field(s) error")
+ .timestamp(timestamp)
+ .developerMessage(exception.getClass().getName())
+ .fields(fields)
+ .fieldsMessage(fieldMessage)
+ .build()
+ );
+ }
+}
diff --git a/src/main/java/com/institutosemprealerta/semprealerta/domain/model/File.java b/src/main/java/com/institutosemprealerta/semprealerta/domain/model/File.java
new file mode 100644
index 0000000..b3aa5a4
--- /dev/null
+++ b/src/main/java/com/institutosemprealerta/semprealerta/domain/model/File.java
@@ -0,0 +1,33 @@
+package com.institutosemprealerta.semprealerta.domain.model;
+
+import lombok.Builder;
+@Builder
+public class File {
+ private String fileName;
+ private String fileDownloadUri;
+ private String fileType;
+
+ public String getFileName() {
+ return fileName;
+ }
+
+ public void setFileName(String fileName) {
+ this.fileName = fileName;
+ }
+
+ public String getFileDownloadUri() {
+ return fileDownloadUri;
+ }
+
+ public void setFileDownloadUri(String fileDownloadUri) {
+ this.fileDownloadUri = fileDownloadUri;
+ }
+
+ public String getFileType() {
+ return fileType;
+ }
+
+ public void setFileType(String fileType) {
+ this.fileType = fileType;
+ }
+}
diff --git a/src/main/java/com/institutosemprealerta/semprealerta/domain/model/Post.java b/src/main/java/com/institutosemprealerta/semprealerta/domain/model/Post.java
new file mode 100644
index 0000000..7ed0db5
--- /dev/null
+++ b/src/main/java/com/institutosemprealerta/semprealerta/domain/model/Post.java
@@ -0,0 +1,46 @@
+package com.institutosemprealerta.semprealerta.domain.model;
+
+import io.swagger.v3.oas.annotations.Hidden;
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.NotBlank;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.time.LocalDateTime;
+
+@Getter
+@Setter
+public class Post {
+
+ @Hidden
+ private Long id;
+
+ @NotBlank(message = "Title é obrigatorio")
+ @Schema(description = "Title do post", example = "Titulo do post")
+ private String title;
+
+ private String slug;
+
+ @NotBlank(message = "Content é obrigatorio")
+ @Schema(description = "Contenteudo do post", example = "Conteudo do post")
+ private String content;
+
+ @NotBlank(message = "Banner é obrigatorio")
+ @Schema(description = "Banner do post", example = "https://www.https://github.com/MatheusVict.png")
+ private String banner;
+
+ @Hidden
+ private LocalDateTime createdAt;
+
+ public Post(Long id, String title, String slug, String content, String banner, LocalDateTime createdAt) {
+ this.id = id;
+ this.title = title;
+ this.slug = slug;
+ this.content = content;
+ this.banner = banner;
+ this.createdAt = createdAt;
+ }
+
+ public Post() {
+ }
+}
diff --git a/src/main/java/com/institutosemprealerta/semprealerta/domain/model/UserDTO.java b/src/main/java/com/institutosemprealerta/semprealerta/domain/model/UserDTO.java
new file mode 100644
index 0000000..004a824
--- /dev/null
+++ b/src/main/java/com/institutosemprealerta/semprealerta/domain/model/UserDTO.java
@@ -0,0 +1,70 @@
+package com.institutosemprealerta.semprealerta.domain.model;
+
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.institutosemprealerta.semprealerta.infrastructure.entity.user.Address;
+import com.institutosemprealerta.semprealerta.infrastructure.entity.user.Contact;
+import com.institutosemprealerta.semprealerta.infrastructure.entity.user.User;
+import com.institutosemprealerta.semprealerta.infrastructure.entity.user.UserRoles;
+import com.institutosemprealerta.semprealerta.utils.DateManipulation;
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.*;
+
+import java.time.LocalDate;
+import java.time.format.DateTimeFormatter;
+
+public record UserDTO(
+ @NotBlank
+ @Schema(description = "Nome do usuário", example = "Matheus Victor")
+ String name,
+ @Email
+ @Schema(description = "Email do usuário", example = "muryllo@gg.com")
+ String email,
+ @NotBlank
+ @Schema(description = "Senha do usuário", example = "123456")
+ String password,
+ @NotBlank
+ @Schema(description = "Telefone do usuário", example = "123456")
+ String phone,
+ @Schema(description = "Gênero do usuário", example = "Masculino")
+ String gender,
+ @PastOrPresent
+ @Schema(description = "Data de nascimento do usuário", example = "1999-12-12")
+ LocalDate birthDate,
+ @NotNull
+ @Schema(description = "Papel do usuário", example = "ADMIN")
+ UserRoles roles,
+ @Schema(description = "Rua do usuário", example = "Rua 1")
+ String street,
+ @Schema(description = "Número da casa do usuário", example = "123")
+ String number,
+ @Schema(description = "Cidade do usuário", example = "Igarassu e Lima")
+ String city,
+ @Schema(description = "CEP do usuário", example = "123456")
+ String zipCode
+
+) {
+ public User toDomain() {
+ //LocalDate birth = DateManipulation.stringToLocalDate(birthDate);
+ Contact contact = new Contact(
+ email,
+ phone
+ );
+
+ Address address = new Address(
+ street,
+ number,
+ city,
+ zipCode
+ );
+ return new User(
+ name,
+ password,
+ gender,
+ birthDate,
+ roles,
+ contact,
+ address
+ );
+ }
+}
diff --git a/src/main/java/com/institutosemprealerta/semprealerta/domain/ports/in/SlugGenerator.java b/src/main/java/com/institutosemprealerta/semprealerta/domain/ports/in/SlugGenerator.java
new file mode 100644
index 0000000..31387bc
--- /dev/null
+++ b/src/main/java/com/institutosemprealerta/semprealerta/domain/ports/in/SlugGenerator.java
@@ -0,0 +1,5 @@
+package com.institutosemprealerta.semprealerta.domain.ports.in;
+
+public interface SlugGenerator {
+ String generate(String input);
+}
diff --git a/src/main/java/com/institutosemprealerta/semprealerta/domain/ports/in/impl/SlugifySlugGenerator.java b/src/main/java/com/institutosemprealerta/semprealerta/domain/ports/in/impl/SlugifySlugGenerator.java
new file mode 100644
index 0000000..b2de9fb
--- /dev/null
+++ b/src/main/java/com/institutosemprealerta/semprealerta/domain/ports/in/impl/SlugifySlugGenerator.java
@@ -0,0 +1,19 @@
+package com.institutosemprealerta.semprealerta.domain.ports.in.impl;
+
+import com.github.slugify.Slugify;
+import com.institutosemprealerta.semprealerta.domain.ports.in.SlugGenerator;
+import org.springframework.stereotype.Component;
+
+@Component
+public class SlugifySlugGenerator implements SlugGenerator {
+ private final Slugify slug;
+
+ public SlugifySlugGenerator() {
+ this.slug = Slugify.builder().build();
+ }
+
+ @Override
+ public String generate(String input) {
+ return slug.slugify(input);
+ }
+}
diff --git a/src/main/java/com/institutosemprealerta/semprealerta/domain/ports/out/FileRepository.java b/src/main/java/com/institutosemprealerta/semprealerta/domain/ports/out/FileRepository.java
new file mode 100644
index 0000000..a1a8b51
--- /dev/null
+++ b/src/main/java/com/institutosemprealerta/semprealerta/domain/ports/out/FileRepository.java
@@ -0,0 +1,13 @@
+package com.institutosemprealerta.semprealerta.domain.ports.out;
+
+import com.institutosemprealerta.semprealerta.domain.model.File;
+import com.institutosemprealerta.semprealerta.domain.ports.out.responses.FileResponse;
+
+import java.util.List;
+
+public interface FileRepository {
+ void save(File file);
+ void delete(Long id);
+ List listAll();
+
+}
diff --git a/src/main/java/com/institutosemprealerta/semprealerta/domain/ports/out/PostRepository.java b/src/main/java/com/institutosemprealerta/semprealerta/domain/ports/out/PostRepository.java
new file mode 100644
index 0000000..34e614c
--- /dev/null
+++ b/src/main/java/com/institutosemprealerta/semprealerta/domain/ports/out/PostRepository.java
@@ -0,0 +1,22 @@
+package com.institutosemprealerta.semprealerta.domain.ports.out;
+
+import com.institutosemprealerta.semprealerta.domain.model.Post;
+import com.institutosemprealerta.semprealerta.infrastructure.entity.post.PostEntity;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.Pageable;
+
+import java.util.List;
+
+public interface PostRepository {
+ String save(Post post);
+
+ void delete(Long id);
+
+ void update(Long id, Post post);
+
+ Page listAll(Pageable pageable);
+
+ Post findBySlug(String slug);
+ Post findById(Long id);
+
+}
diff --git a/src/main/java/com/institutosemprealerta/semprealerta/domain/ports/out/UserRepository.java b/src/main/java/com/institutosemprealerta/semprealerta/domain/ports/out/UserRepository.java
new file mode 100644
index 0000000..42c6d51
--- /dev/null
+++ b/src/main/java/com/institutosemprealerta/semprealerta/domain/ports/out/UserRepository.java
@@ -0,0 +1,15 @@
+package com.institutosemprealerta.semprealerta.domain.ports.out;
+
+import com.institutosemprealerta.semprealerta.infrastructure.entity.user.User;
+
+import java.util.Optional;
+
+public interface UserRepository {
+ void save(User user);
+ Optional findById(int id);
+ void update(int id, User user);
+ void delete(int id);
+ Optional findByRegistration(String registration);
+ Optional findByEmail(String email);
+
+}
diff --git a/src/main/java/com/institutosemprealerta/semprealerta/domain/ports/out/exceptions/ExceptionPattern.java b/src/main/java/com/institutosemprealerta/semprealerta/domain/ports/out/exceptions/ExceptionPattern.java
new file mode 100644
index 0000000..a0c2a12
--- /dev/null
+++ b/src/main/java/com/institutosemprealerta/semprealerta/domain/ports/out/exceptions/ExceptionPattern.java
@@ -0,0 +1,20 @@
+package com.institutosemprealerta.semprealerta.domain.ports.out.exceptions;
+
+import lombok.Builder;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.time.LocalDateTime;
+
+@Getter
+@Setter
+@Builder
+public class ExceptionPattern {
+ private String title;
+ private int status;
+ private String details;
+ private LocalDateTime timestamp;
+ private String developerMessage;
+ private String fields;
+ private String fieldsMessage;
+}
diff --git a/src/main/java/com/institutosemprealerta/semprealerta/domain/ports/out/exceptions/file/FileNotFoundException.java b/src/main/java/com/institutosemprealerta/semprealerta/domain/ports/out/exceptions/file/FileNotFoundException.java
new file mode 100644
index 0000000..be7a345
--- /dev/null
+++ b/src/main/java/com/institutosemprealerta/semprealerta/domain/ports/out/exceptions/file/FileNotFoundException.java
@@ -0,0 +1,7 @@
+package com.institutosemprealerta.semprealerta.domain.ports.out.exceptions.file;
+
+public class FileNotFoundException extends RuntimeException {
+ public FileNotFoundException(String message) {
+ super(message);
+ }
+}
diff --git a/src/main/java/com/institutosemprealerta/semprealerta/domain/ports/out/exceptions/file/InvalidFileException.java b/src/main/java/com/institutosemprealerta/semprealerta/domain/ports/out/exceptions/file/InvalidFileException.java
new file mode 100644
index 0000000..3f082a0
--- /dev/null
+++ b/src/main/java/com/institutosemprealerta/semprealerta/domain/ports/out/exceptions/file/InvalidFileException.java
@@ -0,0 +1,7 @@
+package com.institutosemprealerta.semprealerta.domain.ports.out.exceptions.file;
+
+public class InvalidFileException extends RuntimeException {
+ public InvalidFileException(String message) {
+ super(message);
+ }
+}
diff --git a/src/main/java/com/institutosemprealerta/semprealerta/domain/ports/out/exceptions/post/PostNotFoundException.java b/src/main/java/com/institutosemprealerta/semprealerta/domain/ports/out/exceptions/post/PostNotFoundException.java
new file mode 100644
index 0000000..2ac6a26
--- /dev/null
+++ b/src/main/java/com/institutosemprealerta/semprealerta/domain/ports/out/exceptions/post/PostNotFoundException.java
@@ -0,0 +1,7 @@
+package com.institutosemprealerta.semprealerta.domain.ports.out.exceptions.post;
+
+public class PostNotFoundException extends RuntimeException {
+ public PostNotFoundException(String message) {
+ super(message);
+ }
+}
diff --git a/src/main/java/com/institutosemprealerta/semprealerta/domain/ports/out/exceptions/user/EmailAlreadyExistsException.java b/src/main/java/com/institutosemprealerta/semprealerta/domain/ports/out/exceptions/user/EmailAlreadyExistsException.java
new file mode 100644
index 0000000..f37d95e
--- /dev/null
+++ b/src/main/java/com/institutosemprealerta/semprealerta/domain/ports/out/exceptions/user/EmailAlreadyExistsException.java
@@ -0,0 +1,7 @@
+package com.institutosemprealerta.semprealerta.domain.ports.out.exceptions.user;
+
+public class EmailAlreadyExistsException extends RuntimeException {
+ public EmailAlreadyExistsException(String message) {
+ super(message);
+ }
+}
diff --git a/src/main/java/com/institutosemprealerta/semprealerta/domain/ports/out/exceptions/user/UserNotFoundException.java b/src/main/java/com/institutosemprealerta/semprealerta/domain/ports/out/exceptions/user/UserNotFoundException.java
new file mode 100644
index 0000000..4241ff4
--- /dev/null
+++ b/src/main/java/com/institutosemprealerta/semprealerta/domain/ports/out/exceptions/user/UserNotFoundException.java
@@ -0,0 +1,7 @@
+package com.institutosemprealerta.semprealerta.domain.ports.out.exceptions.user;
+
+public class UserNotFoundException extends RuntimeException {
+ public UserNotFoundException(String message) {
+ super(message);
+ }
+}
diff --git a/src/main/java/com/institutosemprealerta/semprealerta/domain/ports/out/request/LoginDTO.java b/src/main/java/com/institutosemprealerta/semprealerta/domain/ports/out/request/LoginDTO.java
new file mode 100644
index 0000000..ac0a8e1
--- /dev/null
+++ b/src/main/java/com/institutosemprealerta/semprealerta/domain/ports/out/request/LoginDTO.java
@@ -0,0 +1,14 @@
+package com.institutosemprealerta.semprealerta.domain.ports.out.request;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.NotBlank;
+
+public record LoginDTO(
+ @NotBlank(message = "email is mandatory")
+ @Schema(description = "email do usuário", example = "muryllo@email.com")
+ String email,
+ @NotBlank(message = "password is mandatory")
+ @Schema(description = "Senha do usuário", example = "12345")
+ String password
+) {
+}
diff --git a/src/main/java/com/institutosemprealerta/semprealerta/domain/ports/out/responses/FileResponse.java b/src/main/java/com/institutosemprealerta/semprealerta/domain/ports/out/responses/FileResponse.java
new file mode 100644
index 0000000..dd8bbd0
--- /dev/null
+++ b/src/main/java/com/institutosemprealerta/semprealerta/domain/ports/out/responses/FileResponse.java
@@ -0,0 +1,12 @@
+package com.institutosemprealerta.semprealerta.domain.ports.out.responses;
+
+import java.time.LocalDateTime;
+
+public record FileResponse(
+ long id,
+ String fileName,
+ String fileDownloadUri,
+ String fileType,
+ LocalDateTime uploadDate
+) {
+}
diff --git a/src/main/java/com/institutosemprealerta/semprealerta/domain/ports/out/responses/LoginResponse.java b/src/main/java/com/institutosemprealerta/semprealerta/domain/ports/out/responses/LoginResponse.java
new file mode 100644
index 0000000..f72a32a
--- /dev/null
+++ b/src/main/java/com/institutosemprealerta/semprealerta/domain/ports/out/responses/LoginResponse.java
@@ -0,0 +1,11 @@
+package com.institutosemprealerta.semprealerta.domain.ports.out.responses;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
+
+public record LoginResponse(
+ @Schema(description = "token de autorização para acessar os recursos", example = "eyn32nklafjçj354335g35")
+ @JsonProperty("access_token")
+ String accessToken
+) {
+}
diff --git a/src/main/java/com/institutosemprealerta/semprealerta/domain/ports/out/responses/UserResponse.java b/src/main/java/com/institutosemprealerta/semprealerta/domain/ports/out/responses/UserResponse.java
new file mode 100644
index 0000000..0b1b14a
--- /dev/null
+++ b/src/main/java/com/institutosemprealerta/semprealerta/domain/ports/out/responses/UserResponse.java
@@ -0,0 +1,34 @@
+package com.institutosemprealerta.semprealerta.domain.ports.out.responses;
+
+import com.institutosemprealerta.semprealerta.infrastructure.entity.user.Address;
+import com.institutosemprealerta.semprealerta.infrastructure.entity.user.Contact;
+import com.institutosemprealerta.semprealerta.infrastructure.entity.user.User;
+import com.institutosemprealerta.semprealerta.infrastructure.entity.user.UserRoles;
+
+import java.time.LocalDate;
+
+public record UserResponse(
+ String registration,
+ String name,
+
+ String gender,
+ LocalDate birthDate,
+
+ UserRoles roles,
+
+ Contact contact,
+ Address address
+) {
+
+ public static UserResponse toResponse(User user) {
+ return new UserResponse(
+ user.getRegistration(),
+ user.getName(),
+ user.getGender(),
+ user.getBirthDate(),
+ user.getRoles(),
+ user.getContact(),
+ user.getAddress()
+ );
+ }
+}
diff --git a/src/main/java/com/institutosemprealerta/semprealerta/domain/service/AuthenticationService.java b/src/main/java/com/institutosemprealerta/semprealerta/domain/service/AuthenticationService.java
new file mode 100644
index 0000000..1cf782a
--- /dev/null
+++ b/src/main/java/com/institutosemprealerta/semprealerta/domain/service/AuthenticationService.java
@@ -0,0 +1,10 @@
+package com.institutosemprealerta.semprealerta.domain.service;
+
+import com.institutosemprealerta.semprealerta.domain.ports.out.request.LoginDTO;
+import com.institutosemprealerta.semprealerta.domain.ports.out.responses.LoginResponse;
+import com.institutosemprealerta.semprealerta.infrastructure.entity.user.User;
+
+public interface AuthenticationService {
+ LoginResponse login(LoginDTO login);
+ void register(User user);
+}
diff --git a/src/main/java/com/institutosemprealerta/semprealerta/domain/service/PostService.java b/src/main/java/com/institutosemprealerta/semprealerta/domain/service/PostService.java
new file mode 100644
index 0000000..f4ac8c0
--- /dev/null
+++ b/src/main/java/com/institutosemprealerta/semprealerta/domain/service/PostService.java
@@ -0,0 +1,18 @@
+package com.institutosemprealerta.semprealerta.domain.service;
+
+import com.institutosemprealerta.semprealerta.domain.model.Post;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.Pageable;
+
+
+import java.util.List;
+
+public interface PostService {
+ String save(Post post);
+ void delete(Long id);
+ void update(Long id, Post post);
+ Page listAll(Pageable pageable);
+
+ Post findBySlug(String slug);
+ Post findById(Long id);
+}
diff --git a/src/main/java/com/institutosemprealerta/semprealerta/domain/service/StorageService.java b/src/main/java/com/institutosemprealerta/semprealerta/domain/service/StorageService.java
new file mode 100644
index 0000000..ed1106f
--- /dev/null
+++ b/src/main/java/com/institutosemprealerta/semprealerta/domain/service/StorageService.java
@@ -0,0 +1,20 @@
+package com.institutosemprealerta.semprealerta.domain.service;
+
+import com.institutosemprealerta.semprealerta.domain.model.File;
+import com.institutosemprealerta.semprealerta.domain.ports.out.responses.FileResponse;
+import org.springframework.core.io.Resource;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.nio.file.Path;
+import java.util.List;
+import java.util.stream.Stream;
+
+public interface StorageService {
+ void init();
+ String store(MultipartFile file, String fileType);
+ List loadAll();
+ Path load(String filename);
+ Resource loadAsResource(String filename);
+ void delete(String filename);
+ void deleteAll();
+}
diff --git a/src/main/java/com/institutosemprealerta/semprealerta/domain/service/TokenService.java b/src/main/java/com/institutosemprealerta/semprealerta/domain/service/TokenService.java
new file mode 100644
index 0000000..154d3d9
--- /dev/null
+++ b/src/main/java/com/institutosemprealerta/semprealerta/domain/service/TokenService.java
@@ -0,0 +1,9 @@
+package com.institutosemprealerta.semprealerta.domain.service;
+
+import com.institutosemprealerta.semprealerta.domain.model.UserDTO;
+import com.institutosemprealerta.semprealerta.infrastructure.entity.user.User;
+
+public interface TokenService {
+ String generateToken(User user);
+ String validateToken(String token);
+}
diff --git a/src/main/java/com/institutosemprealerta/semprealerta/domain/service/UserService.java b/src/main/java/com/institutosemprealerta/semprealerta/domain/service/UserService.java
new file mode 100644
index 0000000..5e10df6
--- /dev/null
+++ b/src/main/java/com/institutosemprealerta/semprealerta/domain/service/UserService.java
@@ -0,0 +1,12 @@
+package com.institutosemprealerta.semprealerta.domain.service;
+
+import com.institutosemprealerta.semprealerta.infrastructure.entity.user.User;
+
+public interface UserService {
+ void save(User user);
+ void update(int id, User user);
+ void delete(int id);
+ User findByRegistration(String registration);
+ User findByEmail(String email);
+ User findById(int id);
+}
diff --git a/src/main/java/com/institutosemprealerta/semprealerta/domain/service/impl/AuthenticationServiceImpl.java b/src/main/java/com/institutosemprealerta/semprealerta/domain/service/impl/AuthenticationServiceImpl.java
new file mode 100644
index 0000000..5b3e4fe
--- /dev/null
+++ b/src/main/java/com/institutosemprealerta/semprealerta/domain/service/impl/AuthenticationServiceImpl.java
@@ -0,0 +1,40 @@
+package com.institutosemprealerta.semprealerta.domain.service.impl;
+
+import com.institutosemprealerta.semprealerta.domain.ports.out.request.LoginDTO;
+import com.institutosemprealerta.semprealerta.domain.ports.out.responses.LoginResponse;
+import com.institutosemprealerta.semprealerta.domain.service.AuthenticationService;
+import com.institutosemprealerta.semprealerta.domain.service.TokenService;
+import com.institutosemprealerta.semprealerta.infrastructure.entity.user.User;
+import org.springframework.security.authentication.AuthenticationManager;
+import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
+import org.springframework.security.core.Authentication;
+import org.springframework.stereotype.Service;
+
+@Service
+public class AuthenticationServiceImpl implements AuthenticationService {
+
+ private final AuthenticationManager authenticationManager;
+
+ private final TokenService tokenService;
+
+ public AuthenticationServiceImpl(AuthenticationManager authenticationManager, TokenService tokenService) {
+ this.authenticationManager = authenticationManager;
+ this.tokenService = tokenService;
+ }
+
+ @Override
+ public LoginResponse login(LoginDTO login) {
+ UsernamePasswordAuthenticationToken userNamePassword =
+ new UsernamePasswordAuthenticationToken(login.email(), login.password());
+ Authentication auth = this.authenticationManager.authenticate(userNamePassword);
+
+ String token = tokenService.generateToken((User) auth.getPrincipal());
+
+ return new LoginResponse(token);
+ }
+
+ @Override
+ public void register(User user) {
+
+ }
+}
diff --git a/src/main/java/com/institutosemprealerta/semprealerta/domain/service/impl/AuthorizationService.java b/src/main/java/com/institutosemprealerta/semprealerta/domain/service/impl/AuthorizationService.java
new file mode 100644
index 0000000..a1e485d
--- /dev/null
+++ b/src/main/java/com/institutosemprealerta/semprealerta/domain/service/impl/AuthorizationService.java
@@ -0,0 +1,21 @@
+package com.institutosemprealerta.semprealerta.domain.service.impl;
+
+import com.institutosemprealerta.semprealerta.domain.service.UserService;
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.security.core.userdetails.UserDetailsService;
+import org.springframework.security.core.userdetails.UsernameNotFoundException;
+import org.springframework.stereotype.Service;
+
+@Service
+public class AuthorizationService implements UserDetailsService {
+ private final UserService userService;
+
+ public AuthorizationService(UserService userService) {
+ this.userService = userService;
+ }
+
+ @Override
+ public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
+ return userService.findByEmail(username);
+ }
+}
diff --git a/src/main/java/com/institutosemprealerta/semprealerta/domain/service/impl/PostServiceImpl.java b/src/main/java/com/institutosemprealerta/semprealerta/domain/service/impl/PostServiceImpl.java
new file mode 100644
index 0000000..e79e3b6
--- /dev/null
+++ b/src/main/java/com/institutosemprealerta/semprealerta/domain/service/impl/PostServiceImpl.java
@@ -0,0 +1,60 @@
+package com.institutosemprealerta.semprealerta.domain.service.impl;
+
+import com.institutosemprealerta.semprealerta.domain.service.PostService;
+import com.institutosemprealerta.semprealerta.domain.model.Post;
+import com.institutosemprealerta.semprealerta.domain.ports.in.SlugGenerator;
+import com.institutosemprealerta.semprealerta.domain.ports.out.PostRepository;
+import org.springframework.data.domain.Page;
+import org.springframework.stereotype.Service;
+import org.springframework.data.domain.Pageable;
+
+@Service
+public class PostServiceImpl implements PostService {
+ private final PostRepository postRepository;
+ private final SlugGenerator slugGenerator;
+
+ public PostServiceImpl(PostRepository postRepository, SlugGenerator slugGenerator) {
+ this.postRepository = postRepository;
+ this.slugGenerator = slugGenerator;
+ }
+
+ @Override
+ public String save(Post post) {
+ String slug = this.generateSlug(post.getTitle());
+ post.setSlug(slug);
+
+ return postRepository.save(post);
+ }
+
+ @Override
+ public void delete(Long id) {
+ postRepository.delete(id);
+ }
+
+ @Override
+ public void update(Long id, Post post) {
+ String slug = this.generateSlug(post.getTitle());
+ post.setSlug(slug);
+ postRepository.update(id, post);
+ }
+
+ @Override
+ public Page listAll(Pageable pageable) {
+ return postRepository.listAll(pageable);
+ }
+
+
+ @Override
+ public Post findBySlug(String slug) {
+ return postRepository.findBySlug(slug);
+ }
+
+ @Override
+ public Post findById(Long id) {
+ return postRepository.findById(id);
+ }
+
+ private String generateSlug(String title) {
+ return slugGenerator.generate(title);
+ }
+}
diff --git a/src/main/java/com/institutosemprealerta/semprealerta/domain/service/impl/StorageServiceImpl.java b/src/main/java/com/institutosemprealerta/semprealerta/domain/service/impl/StorageServiceImpl.java
new file mode 100644
index 0000000..4085d82
--- /dev/null
+++ b/src/main/java/com/institutosemprealerta/semprealerta/domain/service/impl/StorageServiceImpl.java
@@ -0,0 +1,112 @@
+package com.institutosemprealerta.semprealerta.domain.service.impl;
+
+import com.institutosemprealerta.semprealerta.domain.service.StorageService;
+import com.institutosemprealerta.semprealerta.domain.model.File;
+import com.institutosemprealerta.semprealerta.domain.ports.out.FileRepository;
+import com.institutosemprealerta.semprealerta.domain.ports.out.exceptions.file.FileNotFoundException;
+import com.institutosemprealerta.semprealerta.domain.ports.out.exceptions.file.InvalidFileException;
+import com.institutosemprealerta.semprealerta.domain.ports.out.responses.FileResponse;
+import com.institutosemprealerta.semprealerta.infrastructure.config.FileStorageProperties;
+import org.springframework.core.io.Resource;
+import org.springframework.core.io.UrlResource;
+import org.springframework.stereotype.Service;
+import org.springframework.util.FileSystemUtils;
+import org.springframework.util.StringUtils;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.List;
+
+@Service
+public class StorageServiceImpl implements StorageService {
+ private final Path fileStorageLocation;
+ private final FileRepository fileRepository;
+
+ public StorageServiceImpl(FileStorageProperties fileStorageProperties, FileRepository fileRepository) {
+ this.fileStorageLocation = Paths.get(fileStorageProperties.getUploadDir())
+ .toAbsolutePath().normalize();
+ this.fileRepository = fileRepository;
+ }
+
+ @Override
+ public void init() {
+ try {
+ Files.createDirectories(fileStorageLocation);
+ } catch (IOException e) {
+ throw new RuntimeException("Could not create the directory where the uploaded files will be stored.", e);
+ }
+ }
+
+ @Override
+ public String store(MultipartFile file, String fileType) {
+ if (file.getOriginalFilename() == null || file.getOriginalFilename().isEmpty()) {
+ throw new InvalidFileException("File name is empty");
+ }
+ String fileName = StringUtils.cleanPath(file.getOriginalFilename());
+
+ try {
+ Path targetLocation = fileStorageLocation.resolve(fileName);
+ init();
+
+ file.transferTo(targetLocation.toFile());
+
+ String fileDownloadUri = "/api/v1/files/download/" + fileName;
+
+ File fileData = File.builder()
+ .fileName(fileName)
+ .fileType(fileType)
+ .fileDownloadUri(fileDownloadUri)
+ .build();
+
+ this.fileRepository.save(fileData);
+ } catch (IOException e) {
+ throw new InvalidFileException("Could not store file " + fileName + ". Please try again!");
+ }
+ return fileName;
+ }
+
+ @Override
+ public List loadAll() {
+
+ return this.fileRepository.listAll();
+ }
+
+ @Override
+ public Path load(String filename) {
+ Path file = fileStorageLocation.resolve(filename).normalize();
+ if (!Files.exists(file)) {
+ throw new FileNotFoundException("File not found " + filename);
+ }
+ return file;
+ }
+
+ @Override
+ public Resource loadAsResource(String filename) {
+ URI fileUri = load(filename).toUri();
+ try {
+ return new UrlResource(fileUri);
+ } catch (MalformedURLException e) {
+ throw new InvalidFileException("Throwing exception when trying to read file " + filename + e.getMessage());
+ }
+ }
+
+ @Override
+ public void delete(String filename) {
+ Path file = load(filename);
+ try {
+ Files.deleteIfExists(file);
+ } catch (IOException e) {
+ throw new FileNotFoundException("File not found " + filename);
+ }
+ }
+
+ @Override
+ public void deleteAll() {
+ FileSystemUtils.deleteRecursively(fileStorageLocation.toFile());
+ }
+}
diff --git a/src/main/java/com/institutosemprealerta/semprealerta/domain/service/impl/TokenServiceImpl.java b/src/main/java/com/institutosemprealerta/semprealerta/domain/service/impl/TokenServiceImpl.java
new file mode 100644
index 0000000..3d262d6
--- /dev/null
+++ b/src/main/java/com/institutosemprealerta/semprealerta/domain/service/impl/TokenServiceImpl.java
@@ -0,0 +1,55 @@
+package com.institutosemprealerta.semprealerta.domain.service.impl;
+
+import com.auth0.jwt.JWT;
+import com.auth0.jwt.algorithms.Algorithm;
+import com.auth0.jwt.exceptions.JWTCreationException;
+import com.auth0.jwt.exceptions.JWTVerificationException;
+import com.institutosemprealerta.semprealerta.domain.model.UserDTO;
+import com.institutosemprealerta.semprealerta.domain.service.TokenService;
+import com.institutosemprealerta.semprealerta.infrastructure.entity.user.User;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Service;
+
+import java.time.Instant;
+import java.time.LocalDateTime;
+import java.time.ZoneOffset;
+
+@Service
+public class TokenServiceImpl implements TokenService {
+
+ private String secret = "secret";
+
+ private final Algorithm encryptionAlgorithm = Algorithm.HMAC256(secret);
+
+ private final String issuer = "sempre-alerta";
+
+ @Override
+ public String generateToken(User user) {
+ try {
+ return JWT.create()
+ .withIssuer(issuer)
+ .withSubject(user.getContact().getEmail())
+ .withExpiresAt(generationExpirationDate())
+ .sign(encryptionAlgorithm);
+ } catch (JWTCreationException e) {
+ throw new JWTCreationException("Error while generating token", e);
+ }
+ }
+
+ @Override
+ public String validateToken(String token) {
+ try {
+ return JWT.require(encryptionAlgorithm)
+ .withIssuer(issuer)
+ .build()
+ .verify(token)
+ .getSubject();
+ } catch (JWTVerificationException e) {
+ return "";
+ }
+ }
+
+ private Instant generationExpirationDate() {
+ return LocalDateTime.now().plusHours(2).toInstant(ZoneOffset.of("-03:00"));
+ }
+}
diff --git a/src/main/java/com/institutosemprealerta/semprealerta/domain/service/impl/UserServiceImpl.java b/src/main/java/com/institutosemprealerta/semprealerta/domain/service/impl/UserServiceImpl.java
new file mode 100644
index 0000000..372e151
--- /dev/null
+++ b/src/main/java/com/institutosemprealerta/semprealerta/domain/service/impl/UserServiceImpl.java
@@ -0,0 +1,54 @@
+package com.institutosemprealerta.semprealerta.domain.service.impl;
+
+import com.institutosemprealerta.semprealerta.domain.service.UserService;
+import com.institutosemprealerta.semprealerta.domain.ports.out.exceptions.user.UserNotFoundException;
+import com.institutosemprealerta.semprealerta.infrastructure.entity.user.User;
+import com.institutosemprealerta.semprealerta.domain.ports.out.UserRepository;
+import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
+import org.springframework.stereotype.Service;
+
+@Service
+public class UserServiceImpl implements UserService {
+
+ private final UserRepository userRepository;
+
+ public UserServiceImpl(UserRepository userRepository) {
+ this.userRepository = userRepository;
+ }
+
+ @Override
+ public void save(User user) {
+ String newPassword = new BCryptPasswordEncoder().encode(user.getPassword());
+
+ user.setPassword(newPassword);
+ this.userRepository.save(user);
+ }
+
+ @Override
+ public void update(int id, User user) {
+ this.userRepository.update(id, user);
+ }
+
+ @Override
+ public void delete(int id) {
+ this.userRepository.delete(id);
+ }
+
+ @Override
+ public User findByRegistration(String registration) {
+ return this.userRepository.findByRegistration(registration)
+ .orElseThrow(() -> new UserNotFoundException("User not found"));
+ }
+
+ @Override
+ public User findByEmail(String email) {
+ return this.userRepository.findByEmail(email)
+ .orElseThrow(() -> new UserNotFoundException("User not found"));
+ }
+
+ @Override
+ public User findById(int id) {
+ return this.userRepository.findById(id)
+ .orElseThrow(() -> new UserNotFoundException("User not found"));
+ }
+}
diff --git a/src/main/java/com/institutosemprealerta/semprealerta/infrastructure/adpters/JpaFileRepositoryAdapter.java b/src/main/java/com/institutosemprealerta/semprealerta/infrastructure/adpters/JpaFileRepositoryAdapter.java
new file mode 100644
index 0000000..5b37978
--- /dev/null
+++ b/src/main/java/com/institutosemprealerta/semprealerta/infrastructure/adpters/JpaFileRepositoryAdapter.java
@@ -0,0 +1,38 @@
+package com.institutosemprealerta.semprealerta.infrastructure.adpters;
+
+import com.institutosemprealerta.semprealerta.domain.model.File;
+import com.institutosemprealerta.semprealerta.domain.ports.out.FileRepository;
+import com.institutosemprealerta.semprealerta.domain.ports.out.responses.FileResponse;
+import com.institutosemprealerta.semprealerta.infrastructure.entity.file.FileEntity;
+import com.institutosemprealerta.semprealerta.infrastructure.repositories.JpaFileRepository;
+import org.springframework.stereotype.Component;
+
+import java.util.List;
+
+@Component
+public class JpaFileRepositoryAdapter implements FileRepository {
+
+ private final JpaFileRepository fileRepository;
+
+ public JpaFileRepositoryAdapter(JpaFileRepository fileRepository) {
+ this.fileRepository = fileRepository;
+ }
+
+ @Override
+ public void save(File file) {
+ FileEntity fileEntity = FileEntity.fromDomainToModel(file);
+ fileRepository.save(fileEntity);
+ }
+
+ @Override
+ public void delete(Long id) {
+ fileRepository.deleteById(id);
+ }
+
+ @Override
+ public List listAll() {
+ return fileRepository.findAll().stream()
+ .map(FileEntity::toResponse)
+ .toList();
+ }
+}
diff --git a/src/main/java/com/institutosemprealerta/semprealerta/infrastructure/adpters/JpaPostRepositoryAdapter.java b/src/main/java/com/institutosemprealerta/semprealerta/infrastructure/adpters/JpaPostRepositoryAdapter.java
new file mode 100644
index 0000000..fee725c
--- /dev/null
+++ b/src/main/java/com/institutosemprealerta/semprealerta/infrastructure/adpters/JpaPostRepositoryAdapter.java
@@ -0,0 +1,71 @@
+package com.institutosemprealerta.semprealerta.infrastructure.adpters;
+
+import com.institutosemprealerta.semprealerta.domain.model.Post;
+import com.institutosemprealerta.semprealerta.domain.ports.out.PostRepository;
+import com.institutosemprealerta.semprealerta.domain.ports.out.exceptions.post.PostNotFoundException;
+import com.institutosemprealerta.semprealerta.infrastructure.entity.post.PostEntity;
+import com.institutosemprealerta.semprealerta.infrastructure.repositories.JpaPostRepository;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.Pageable;
+import org.springframework.stereotype.Component;
+
+@Component
+public class JpaPostRepositoryAdapter implements PostRepository {
+ private final JpaPostRepository jpaPostRepository;
+
+ public JpaPostRepositoryAdapter(JpaPostRepository jpaPostRepository) {
+ this.jpaPostRepository = jpaPostRepository;
+ }
+
+ @Override
+ public String save(Post post) {
+ boolean slugAlreadyExists = slugAlreadyExists(post.getSlug());
+
+ if (slugAlreadyExists) {
+ String newSlug = post.getSlug() + "-" + Math.random();
+ post.setSlug(newSlug);
+ }
+
+ PostEntity postToSave = PostEntity.fromModel(post);
+ PostEntity postSaved = jpaPostRepository.save(postToSave);
+ return postSaved.getSlug();
+ }
+
+ @Override
+ public void delete(Long id) {
+ this.findById(id);
+ jpaPostRepository.deleteById(id);
+ }
+
+ @Override
+ public void update(Long id, Post post) {
+ this.findById(id);
+ PostEntity postToUpdate = PostEntity.fromModel(post);
+ postToUpdate.setId(id);
+ jpaPostRepository.save(postToUpdate);
+ }
+
+ @Override
+ public Page listAll(Pageable pageable) {
+ return jpaPostRepository.findAll(pageable)
+ .map(postEntity -> PostEntity.toModel(postEntity));
+ }
+
+ @Override
+ public Post findBySlug(String slug) {
+ return jpaPostRepository.findBySlug(slug)
+ .map(postEntity -> PostEntity.toModel(postEntity))
+ .orElseThrow(() -> new PostNotFoundException("Post not found"));
+ }
+
+ @Override
+ public Post findById(Long id) {
+ return jpaPostRepository.findById(id)
+ .map(postEntity -> PostEntity.toModel(postEntity))
+ .orElseThrow(() -> new PostNotFoundException("Post not found"));
+ }
+
+ private boolean slugAlreadyExists(String slug) {
+ return jpaPostRepository.findBySlug(slug).isPresent();
+ }
+}
diff --git a/src/main/java/com/institutosemprealerta/semprealerta/infrastructure/adpters/JpaUserRepositoryAdapter.java b/src/main/java/com/institutosemprealerta/semprealerta/infrastructure/adpters/JpaUserRepositoryAdapter.java
new file mode 100644
index 0000000..9875a61
--- /dev/null
+++ b/src/main/java/com/institutosemprealerta/semprealerta/infrastructure/adpters/JpaUserRepositoryAdapter.java
@@ -0,0 +1,60 @@
+package com.institutosemprealerta.semprealerta.infrastructure.adpters;
+
+import com.institutosemprealerta.semprealerta.domain.ports.out.UserRepository;
+import com.institutosemprealerta.semprealerta.domain.ports.out.exceptions.user.UserNotFoundException;
+import com.institutosemprealerta.semprealerta.infrastructure.entity.user.User;
+import com.institutosemprealerta.semprealerta.infrastructure.repositories.JpaUserRepository;
+import org.springframework.stereotype.Component;
+
+import java.util.Optional;
+
+@Component
+public class JpaUserRepositoryAdapter implements UserRepository {
+
+ private final JpaUserRepository userRepository;
+
+ public JpaUserRepositoryAdapter(JpaUserRepository jpaUserRepository) {
+ this.userRepository = jpaUserRepository;
+ }
+
+ @Override
+ public void save(User user) {
+ this.userRepository.save(user);
+ }
+
+ @Override
+ public Optional findById(int id) {
+ return this.userRepository.findById(id);
+ }
+
+ @Override
+ public void update(int id, User user) {
+ User userToUpdate = this.userRepository.findById(id)
+ .orElseThrow(() -> new UserNotFoundException("User not found"));
+
+ user.setId(userToUpdate.getId());
+ user.setRegistration(userToUpdate.getRegistration());
+
+ this.userRepository.save(user);
+ }
+
+ @Override
+ public void delete(int id) {
+ User userToDelete = this.userRepository.findById(id)
+ .orElseThrow(() -> new RuntimeException("User not found"));
+
+ this.userRepository.delete(userToDelete);
+ }
+
+ @Override
+ public Optional findByRegistration(String registration) {
+ return this.userRepository.findByRegistration(registration);
+ }
+
+ @Override
+ public Optional findByEmail(String email) {
+ return this.userRepository.findByEmail(email);
+ }
+
+
+}
diff --git a/src/main/java/com/institutosemprealerta/semprealerta/infrastructure/config/ApplicationConfig.java b/src/main/java/com/institutosemprealerta/semprealerta/infrastructure/config/ApplicationConfig.java
new file mode 100644
index 0000000..b7adbce
--- /dev/null
+++ b/src/main/java/com/institutosemprealerta/semprealerta/infrastructure/config/ApplicationConfig.java
@@ -0,0 +1,58 @@
+package com.institutosemprealerta.semprealerta.infrastructure.config;
+
+import com.institutosemprealerta.semprealerta.domain.ports.in.SlugGenerator;
+import com.institutosemprealerta.semprealerta.domain.ports.in.impl.SlugifySlugGenerator;
+import io.swagger.v3.oas.models.Components;
+import io.swagger.v3.oas.models.OpenAPI;
+import io.swagger.v3.oas.models.info.Contact;
+import io.swagger.v3.oas.models.info.Info;
+import io.swagger.v3.oas.models.info.License;
+import io.swagger.v3.oas.models.security.SecurityRequirement;
+import io.swagger.v3.oas.models.security.SecurityScheme;
+import io.swagger.v3.oas.models.servers.Server;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.data.domain.PageRequest;
+import org.springframework.data.domain.Pageable;
+import org.springframework.data.domain.Sort;
+
+import java.util.List;
+
+@Configuration
+public class ApplicationConfig {
+
+ @Bean
+ public SlugGenerator slugGenerator() {
+ return new SlugifySlugGenerator();
+ }
+
+ @Bean
+ public Pageable defaultPageable() {
+ return PageRequest.of(0, 10, Sort.by("createdAt").descending());
+ }
+
+ public SecurityScheme createAPIKeyScheme() {
+ return new SecurityScheme()
+ .type(SecurityScheme.Type.HTTP)
+ .bearerFormat("JWT")
+ .scheme("bearer");
+ }
+
+ @Bean
+ public OpenAPI openAPI() {
+ return new OpenAPI()
+ .addSecurityItem(new SecurityRequirement()
+ .addList("Bearer Authentication"))
+ .components(new Components().addSecuritySchemes(
+ "Bearer Authentication",
+ createAPIKeyScheme()
+ ))
+ .info(new Info().title("Instituto Sempre Alerta API")
+ .description("API do Instituto Sempre Alerta.")
+ .version("1.0").contact(new Contact().name("Matheus Victor")
+ .email("matheusvictorhenrique@gmail.com")
+ .url("https://www.instituto-sempre-alerta.com.br/"))
+ .license(new License().name("License of API")
+ .url("https://opensource.org/license/mit/")));
+ }
+}
diff --git a/src/main/java/com/institutosemprealerta/semprealerta/infrastructure/config/FileStorageProperties.java b/src/main/java/com/institutosemprealerta/semprealerta/infrastructure/config/FileStorageProperties.java
new file mode 100644
index 0000000..0624cb3
--- /dev/null
+++ b/src/main/java/com/institutosemprealerta/semprealerta/infrastructure/config/FileStorageProperties.java
@@ -0,0 +1,18 @@
+package com.institutosemprealerta.semprealerta.infrastructure.config;
+
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+@ConfigurationProperties(prefix = "file")
+public class FileStorageProperties {
+ private String uploadDir;
+
+ public String getUploadDir() {
+ return uploadDir;
+ }
+
+ public void setUploadDir(String uploadDir) {
+ this.uploadDir = uploadDir;
+ }
+}
diff --git a/src/main/java/com/institutosemprealerta/semprealerta/infrastructure/config/security/SecurityConfigurations.java b/src/main/java/com/institutosemprealerta/semprealerta/infrastructure/config/security/SecurityConfigurations.java
new file mode 100644
index 0000000..07b1b0b
--- /dev/null
+++ b/src/main/java/com/institutosemprealerta/semprealerta/infrastructure/config/security/SecurityConfigurations.java
@@ -0,0 +1,71 @@
+package com.institutosemprealerta.semprealerta.infrastructure.config.security;
+
+import lombok.AllArgsConstructor;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.http.HttpMethod;
+import org.springframework.security.authentication.AuthenticationManager;
+import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
+import org.springframework.security.config.annotation.web.builders.HttpSecurity;
+import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
+import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
+import org.springframework.security.config.http.SessionCreationPolicy;
+import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
+import org.springframework.security.crypto.password.PasswordEncoder;
+import org.springframework.security.web.SecurityFilterChain;
+import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
+
+@Configuration
+@EnableWebSecurity
+@AllArgsConstructor
+public class SecurityConfigurations {
+
+ private final securtityFilter securtityFilter;
+
+ private final String[] AUTH_SWAGGER_WHITELIST = {
+ "/swagger-ui/**",
+ "/swagger-ui",
+ "/swagger-resources/**",
+ "/webjars/**",
+ "/v3/api-docs/**",
+ "/swagger-ui.html"
+ };
+
+ private final String[] ACTUATOR_WHITELIST = {
+ "/actuator",
+ "/actuator/health",
+ "/actuator/health/**"
+ };
+
+ @Bean
+ public SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity) throws Exception {
+ return httpSecurity
+ .csrf(AbstractHttpConfigurer::disable)
+ .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
+ .authorizeHttpRequests(authorize -> authorize
+ .requestMatchers(AUTH_SWAGGER_WHITELIST).permitAll()
+ .requestMatchers(ACTUATOR_WHITELIST).permitAll()
+ .requestMatchers(HttpMethod.POST, "/auth/login").permitAll()
+ .requestMatchers("/api/v1/user/**").hasRole("ADMIN")
+ .requestMatchers(HttpMethod.POST, "/api/v1/files/upload").hasRole("ADMIN")
+ .requestMatchers(HttpMethod.POST, "/api/v1/posts/").hasRole("ADMIN")
+ .requestMatchers(HttpMethod.PUT, "/api/v1/posts/**").hasRole("ADMIN")
+ .requestMatchers(HttpMethod.DELETE, "/api/v1/posts/**").hasRole("ADMIN")
+ .anyRequest().authenticated()
+ )
+ .addFilterBefore(securtityFilter, UsernamePasswordAuthenticationFilter.class)
+ .build();
+ }
+
+ @Bean
+ public AuthenticationManager authenticationManager(
+ AuthenticationConfiguration authenticationConfiguration
+ ) throws Exception {
+ return authenticationConfiguration.getAuthenticationManager();
+ }
+
+ @Bean
+ public PasswordEncoder passwordEncoder() {
+ return new BCryptPasswordEncoder();
+ }
+}
diff --git a/src/main/java/com/institutosemprealerta/semprealerta/infrastructure/config/security/securtityFilter.java b/src/main/java/com/institutosemprealerta/semprealerta/infrastructure/config/security/securtityFilter.java
new file mode 100644
index 0000000..9eb9f7f
--- /dev/null
+++ b/src/main/java/com/institutosemprealerta/semprealerta/infrastructure/config/security/securtityFilter.java
@@ -0,0 +1,53 @@
+package com.institutosemprealerta.semprealerta.infrastructure.config.security;
+
+import com.institutosemprealerta.semprealerta.domain.service.TokenService;
+import com.institutosemprealerta.semprealerta.domain.service.UserService;
+import jakarta.servlet.FilterChain;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.stereotype.Component;
+import org.springframework.web.filter.OncePerRequestFilter;
+
+import java.io.IOException;
+
+@Component
+public class securtityFilter extends OncePerRequestFilter {
+ private final TokenService tokenService;
+ private final UserService userService;
+
+ public securtityFilter(TokenService tokenService, UserService userService) {
+ this.tokenService = tokenService;
+ this.userService = userService;
+ }
+
+ @Override
+ protected void doFilterInternal(
+ HttpServletRequest request,
+ HttpServletResponse response,
+ FilterChain filterChain
+ ) throws ServletException, IOException {
+ String token = this.recoverToken(request);
+ if (token != null) {
+ String email = tokenService.validateToken(token);
+ UserDetails user = userService.findByEmail(email);
+
+ UsernamePasswordAuthenticationToken authentication =
+ new UsernamePasswordAuthenticationToken(user, null, user.getAuthorities());
+ SecurityContextHolder.getContext().setAuthentication(authentication);
+
+ }
+ filterChain.doFilter(request, response);
+ }
+
+ private String recoverToken(HttpServletRequest request) {
+ String authHeader = request.getHeader("Authorization");
+ if (authHeader == null || !authHeader.startsWith("Bearer ")) {
+ return null;
+ }
+ return authHeader.substring(7, authHeader.length());
+ }
+}
diff --git a/src/main/java/com/institutosemprealerta/semprealerta/infrastructure/entity/file/FileEntity.java b/src/main/java/com/institutosemprealerta/semprealerta/infrastructure/entity/file/FileEntity.java
new file mode 100644
index 0000000..0d55bad
--- /dev/null
+++ b/src/main/java/com/institutosemprealerta/semprealerta/infrastructure/entity/file/FileEntity.java
@@ -0,0 +1,54 @@
+package com.institutosemprealerta.semprealerta.infrastructure.entity.file;
+
+import com.institutosemprealerta.semprealerta.domain.model.File;
+import com.institutosemprealerta.semprealerta.domain.ports.out.responses.FileResponse;
+import jakarta.persistence.*;
+import lombok.Getter;
+import lombok.Setter;
+import org.hibernate.annotations.CreationTimestamp;
+
+import java.time.LocalDateTime;
+
+@Entity
+@Table(name = "files")
+@Getter
+@Setter
+public class FileEntity {
+ @Id
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ private Long id;
+
+ private String fileName;
+ private String fileDownloadUri;
+ private String fileType;
+
+ @CreationTimestamp
+ private LocalDateTime uploadDate;
+
+ public FileEntity(String fileName, String fileDownloadUri, String fileType) {
+ this.fileName = fileName;
+ this.fileDownloadUri = fileDownloadUri;
+ this.fileType = fileType;
+ }
+
+ public FileEntity() {
+ }
+
+ public static FileEntity fromDomainToModel(File file) {
+ return new FileEntity(
+ file.getFileName(),
+ file.getFileDownloadUri(),
+ file.getFileType()
+ );
+ }
+
+ public static FileResponse toResponse(FileEntity fileEntity) {
+ return new FileResponse(
+ fileEntity.getId(),
+ fileEntity.getFileName(),
+ fileEntity.getFileDownloadUri(),
+ fileEntity.getFileType(),
+ fileEntity.getUploadDate()
+ );
+ }
+}
diff --git a/src/main/java/com/institutosemprealerta/semprealerta/infrastructure/entity/post/PostEntity.java b/src/main/java/com/institutosemprealerta/semprealerta/infrastructure/entity/post/PostEntity.java
new file mode 100644
index 0000000..ac50c6f
--- /dev/null
+++ b/src/main/java/com/institutosemprealerta/semprealerta/infrastructure/entity/post/PostEntity.java
@@ -0,0 +1,67 @@
+package com.institutosemprealerta.semprealerta.infrastructure.entity.post;
+
+import com.institutosemprealerta.semprealerta.domain.model.Post;
+import jakarta.persistence.*;
+import lombok.Getter;
+import lombok.Setter;
+import org.hibernate.annotations.CreationTimestamp;
+
+import java.time.LocalDateTime;
+
+@Setter
+@Getter
+@Entity
+@Table(name = "post")
+public class PostEntity {
+ @Id
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ private Long id;
+ @Column(nullable = false)
+ private String title;
+ @Column(nullable = false)
+ private String slug;
+ @Column(columnDefinition = "TEXT")
+ private String content;
+ private String banner;
+ @CreationTimestamp
+ @Column(nullable = false, updatable = false)
+ private LocalDateTime createdAt;
+
+ public PostEntity() {
+ }
+
+ public PostEntity(Long id, String title, String slug, String content, String banner, LocalDateTime createdAt) {
+ this.id = id;
+ this.title = title;
+ this.slug = slug;
+ this.content = content;
+ this.banner = banner;
+ this.createdAt = createdAt;
+ }
+
+ public PostEntity(String title, String slug, String content, String banner) {
+ this.title = title;
+ this.slug = slug;
+ this.content = content;
+ this.banner = banner;
+ }
+
+ public static PostEntity fromModel(Post post) {
+ PostEntity postEntity = new PostEntity();
+ postEntity.setId(post.getId());
+ postEntity.setTitle(post.getTitle());
+ postEntity.setSlug(post.getSlug());
+ postEntity.setContent(post.getContent());
+ postEntity.setBanner(post.getBanner());
+ return postEntity;
+ }
+
+ public static Post toModel(PostEntity postEntity) {
+ return new Post(postEntity.getId(), postEntity.getTitle(), postEntity.getSlug(), postEntity.getContent(), postEntity.getBanner(), postEntity.getCreatedAt());
+ }
+
+ public Post toModel() {
+ return new Post(this.getId(), this.getTitle(), this.getSlug(), this.getContent(), this.getBanner(), this.getCreatedAt());
+ }
+
+}
diff --git a/src/main/java/com/institutosemprealerta/semprealerta/infrastructure/entity/user/Address.java b/src/main/java/com/institutosemprealerta/semprealerta/infrastructure/entity/user/Address.java
new file mode 100644
index 0000000..9f09f59
--- /dev/null
+++ b/src/main/java/com/institutosemprealerta/semprealerta/infrastructure/entity/user/Address.java
@@ -0,0 +1,19 @@
+package com.institutosemprealerta.semprealerta.infrastructure.entity.user;
+
+import jakarta.persistence.Embeddable;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+@Getter
+@Setter
+@AllArgsConstructor
+@NoArgsConstructor
+@Embeddable
+public class Address {
+ private String street;
+ private String number;
+ private String city;
+ private String zipCode;
+}
diff --git a/src/main/java/com/institutosemprealerta/semprealerta/infrastructure/entity/user/Contact.java b/src/main/java/com/institutosemprealerta/semprealerta/infrastructure/entity/user/Contact.java
new file mode 100644
index 0000000..5c48e24
--- /dev/null
+++ b/src/main/java/com/institutosemprealerta/semprealerta/infrastructure/entity/user/Contact.java
@@ -0,0 +1,17 @@
+package com.institutosemprealerta.semprealerta.infrastructure.entity.user;
+
+import jakarta.persistence.Embeddable;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+@Getter
+@Setter
+@NoArgsConstructor
+@AllArgsConstructor
+@Embeddable
+public class Contact {
+ private String email;
+ private String phone;
+}
diff --git a/src/main/java/com/institutosemprealerta/semprealerta/infrastructure/entity/user/User.java b/src/main/java/com/institutosemprealerta/semprealerta/infrastructure/entity/user/User.java
new file mode 100644
index 0000000..8876141
--- /dev/null
+++ b/src/main/java/com/institutosemprealerta/semprealerta/infrastructure/entity/user/User.java
@@ -0,0 +1,126 @@
+package com.institutosemprealerta.semprealerta.infrastructure.entity.user;
+
+
+import com.institutosemprealerta.semprealerta.domain.model.UserDTO;
+import com.institutosemprealerta.semprealerta.utils.DateManipulation;
+import jakarta.persistence.*;
+import lombok.Getter;
+import lombok.Setter;
+import org.hibernate.annotations.CreationTimestamp;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.authority.SimpleGrantedAuthority;
+import org.springframework.security.core.userdetails.UserDetails;
+
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.util.Collection;
+import java.util.List;
+import java.util.Random;
+
+
+@Entity
+@Table(name = "users")
+@Getter
+@Setter
+public class User implements UserDetails {
+ @Id
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ private Long id;
+ @Column(unique = true)
+ private String registration;
+ private String name;
+ private String password;
+ private String gender;
+ private LocalDate birthDate;
+
+ private UserRoles roles;
+ @Embedded
+ private Contact contact;
+
+ @Embedded
+ private Address address;
+
+ @CreationTimestamp
+ @Column(name = "created_at", updatable = false, columnDefinition = "TIMESTAMP DEFAULT CURRENT_TIMESTAMP")
+ private LocalDateTime createdAt;
+
+ public User() {
+ }
+
+
+ public User(String name, String password, String gender, LocalDate birthDate, UserRoles roles, Contact contact, Address address) {
+ this.name = name;
+ this.password = password;
+ this.gender = gender;
+ this.birthDate = birthDate;
+ this.roles = roles;
+ this.contact = contact;
+ this.address = address;
+ }
+
+
+ @PrePersist
+ public void generateRegistration() {
+ String prefix = this.name.substring(0, 3).toLowerCase() + "-";
+ this.registration = generateRegistration(prefix);
+ }
+
+ private String generateRegistration(String prefix) {
+ StringBuilder registration = new StringBuilder(prefix);
+ Random random = new Random();
+
+ for (int i = 0; i < 8; i++) {
+ int digit = random.nextInt(10);
+ registration.append(digit);
+ }
+
+ return registration.toString();
+ }
+
+ public User fromModelToDomain(UserDTO dto) {
+ //LocalDate birth = DateManipulation.stringToLocalDate(dto.birthDate());
+ return new User(
+ dto.name(),
+ dto.password(),
+ dto.gender(),
+ dto.birthDate(),
+ dto.roles(),
+ new Contact(dto.email(), dto.phone()),
+ new Address(dto.street(), dto.number(), dto.city(), dto.zipCode())
+ );
+ }
+
+ @Override
+ public Collection extends GrantedAuthority> getAuthorities() {
+ if (this.roles == UserRoles.ADMIN) {
+ return List.of(new SimpleGrantedAuthority("ROLE_ADMIN"), new SimpleGrantedAuthority("ROLE_USER"));
+ } else {
+ return List.of(new SimpleGrantedAuthority("ROLE_USER"));
+ }
+ }
+
+ @Override
+ public String getUsername() {
+ return this.contact.getEmail();
+ }
+
+ @Override
+ public boolean isAccountNonExpired() {
+ return true;
+ }
+
+ @Override
+ public boolean isAccountNonLocked() {
+ return true;
+ }
+
+ @Override
+ public boolean isCredentialsNonExpired() {
+ return true;
+ }
+
+ @Override
+ public boolean isEnabled() {
+ return true;
+ }
+}
diff --git a/src/main/java/com/institutosemprealerta/semprealerta/infrastructure/entity/user/UserRoles.java b/src/main/java/com/institutosemprealerta/semprealerta/infrastructure/entity/user/UserRoles.java
new file mode 100644
index 0000000..330bb8f
--- /dev/null
+++ b/src/main/java/com/institutosemprealerta/semprealerta/infrastructure/entity/user/UserRoles.java
@@ -0,0 +1,16 @@
+package com.institutosemprealerta.semprealerta.infrastructure.entity.user;
+
+public enum UserRoles {
+ ADMIN("ADMIN"),
+ USER("USER");
+
+ private final String role;
+
+ UserRoles(String role) {
+ this.role = role;
+ }
+
+ public String getRole() {
+ return role;
+ }
+}
diff --git a/src/main/java/com/institutosemprealerta/semprealerta/infrastructure/repositories/JpaFileRepository.java b/src/main/java/com/institutosemprealerta/semprealerta/infrastructure/repositories/JpaFileRepository.java
new file mode 100644
index 0000000..822c2d0
--- /dev/null
+++ b/src/main/java/com/institutosemprealerta/semprealerta/infrastructure/repositories/JpaFileRepository.java
@@ -0,0 +1,9 @@
+package com.institutosemprealerta.semprealerta.infrastructure.repositories;
+
+import com.institutosemprealerta.semprealerta.infrastructure.entity.file.FileEntity;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public interface JpaFileRepository extends JpaRepository {
+}
diff --git a/src/main/java/com/institutosemprealerta/semprealerta/infrastructure/repositories/JpaPostRepository.java b/src/main/java/com/institutosemprealerta/semprealerta/infrastructure/repositories/JpaPostRepository.java
new file mode 100644
index 0000000..bac153a
--- /dev/null
+++ b/src/main/java/com/institutosemprealerta/semprealerta/infrastructure/repositories/JpaPostRepository.java
@@ -0,0 +1,12 @@
+package com.institutosemprealerta.semprealerta.infrastructure.repositories;
+
+import com.institutosemprealerta.semprealerta.infrastructure.entity.post.PostEntity;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+
+import java.util.Optional;
+
+@Repository
+public interface JpaPostRepository extends JpaRepository{
+ Optional findBySlug(String slug);
+}
diff --git a/src/main/java/com/institutosemprealerta/semprealerta/infrastructure/repositories/JpaUserRepository.java b/src/main/java/com/institutosemprealerta/semprealerta/infrastructure/repositories/JpaUserRepository.java
new file mode 100644
index 0000000..fd4967e
--- /dev/null
+++ b/src/main/java/com/institutosemprealerta/semprealerta/infrastructure/repositories/JpaUserRepository.java
@@ -0,0 +1,16 @@
+package com.institutosemprealerta.semprealerta.infrastructure.repositories;
+
+import com.institutosemprealerta.semprealerta.infrastructure.entity.user.User;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.Query;
+import org.springframework.stereotype.Repository;
+
+import java.util.Optional;
+
+@Repository
+public interface JpaUserRepository extends JpaRepository {
+ @Query("SELECT u FROM User u WHERE u.contact.email = ?1")
+ Optional findByEmail(String email);
+
+ Optional findByRegistration(String registration);
+}
diff --git a/src/main/java/com/institutosemprealerta/semprealerta/swagger/annotations/BadRequestResponse.java b/src/main/java/com/institutosemprealerta/semprealerta/swagger/annotations/BadRequestResponse.java
new file mode 100644
index 0000000..0ebeb1f
--- /dev/null
+++ b/src/main/java/com/institutosemprealerta/semprealerta/swagger/annotations/BadRequestResponse.java
@@ -0,0 +1,18 @@
+package com.institutosemprealerta.semprealerta.swagger.annotations;
+
+import com.institutosemprealerta.semprealerta.domain.ports.out.exceptions.ExceptionPattern;
+import io.swagger.v3.oas.annotations.media.Content;
+import io.swagger.v3.oas.annotations.media.Schema;
+import io.swagger.v3.oas.annotations.responses.ApiResponse;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Target({ElementType.METHOD, ElementType.TYPE})
+@Retention(RetentionPolicy.RUNTIME)
+@ApiResponse(responseCode = "400", description = "Erro de requisição inválida, no lado do cliente",
+ content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionPattern.class)))
+public @interface BadRequestResponse {
+}
diff --git a/src/main/java/com/institutosemprealerta/semprealerta/swagger/annotations/ConflictResponse.java b/src/main/java/com/institutosemprealerta/semprealerta/swagger/annotations/ConflictResponse.java
new file mode 100644
index 0000000..0dbe12c
--- /dev/null
+++ b/src/main/java/com/institutosemprealerta/semprealerta/swagger/annotations/ConflictResponse.java
@@ -0,0 +1,18 @@
+package com.institutosemprealerta.semprealerta.swagger.annotations;
+
+import com.institutosemprealerta.semprealerta.domain.ports.out.exceptions.ExceptionPattern;
+import io.swagger.v3.oas.annotations.media.Content;
+import io.swagger.v3.oas.annotations.media.Schema;
+import io.swagger.v3.oas.annotations.responses.ApiResponse;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Target({ElementType.METHOD, ElementType.TYPE})
+@Retention(RetentionPolicy.RUNTIME)
+@ApiResponse(responseCode = "409", description = "Possui alguns conflitos na requisição",
+ content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionPattern.class)))
+public @interface ConflictResponse {
+}
diff --git a/src/main/java/com/institutosemprealerta/semprealerta/swagger/annotations/CreatedResponse.java b/src/main/java/com/institutosemprealerta/semprealerta/swagger/annotations/CreatedResponse.java
new file mode 100644
index 0000000..8ce4829
--- /dev/null
+++ b/src/main/java/com/institutosemprealerta/semprealerta/swagger/annotations/CreatedResponse.java
@@ -0,0 +1,14 @@
+package com.institutosemprealerta.semprealerta.swagger.annotations;
+
+import io.swagger.v3.oas.annotations.responses.ApiResponse;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Target({ElementType.METHOD, ElementType.TYPE})
+@Retention(RetentionPolicy.RUNTIME)
+@ApiResponse(responseCode = "201", description = "Criado com sucesso", useReturnTypeSchema = true)
+public @interface CreatedResponse {
+}
diff --git a/src/main/java/com/institutosemprealerta/semprealerta/swagger/annotations/NoContentResponse.java b/src/main/java/com/institutosemprealerta/semprealerta/swagger/annotations/NoContentResponse.java
new file mode 100644
index 0000000..8016606
--- /dev/null
+++ b/src/main/java/com/institutosemprealerta/semprealerta/swagger/annotations/NoContentResponse.java
@@ -0,0 +1,14 @@
+package com.institutosemprealerta.semprealerta.swagger.annotations;
+
+import io.swagger.v3.oas.annotations.responses.ApiResponse;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Target({ElementType.METHOD, ElementType.TYPE})
+@Retention(RetentionPolicy.RUNTIME)
+@ApiResponse(responseCode = "204", description = "Requisição bem sucedida e sem retorno", useReturnTypeSchema = true)
+public @interface NoContentResponse {
+}
diff --git a/src/main/java/com/institutosemprealerta/semprealerta/swagger/annotations/NotFoundResponse.java b/src/main/java/com/institutosemprealerta/semprealerta/swagger/annotations/NotFoundResponse.java
new file mode 100644
index 0000000..9eb6e93
--- /dev/null
+++ b/src/main/java/com/institutosemprealerta/semprealerta/swagger/annotations/NotFoundResponse.java
@@ -0,0 +1,18 @@
+package com.institutosemprealerta.semprealerta.swagger.annotations;
+
+import com.institutosemprealerta.semprealerta.domain.ports.out.exceptions.ExceptionPattern;
+import io.swagger.v3.oas.annotations.media.Content;
+import io.swagger.v3.oas.annotations.media.Schema;
+import io.swagger.v3.oas.annotations.responses.ApiResponse;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Target({ElementType.METHOD, ElementType.TYPE})
+@Retention(RetentionPolicy.RUNTIME)
+@ApiResponse(responseCode = "404", description = "Objeto não encontrado",
+ content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionPattern.class)))
+public @interface NotFoundResponse {
+}
diff --git a/src/main/java/com/institutosemprealerta/semprealerta/swagger/annotations/OkResponse.java b/src/main/java/com/institutosemprealerta/semprealerta/swagger/annotations/OkResponse.java
new file mode 100644
index 0000000..cf40ec7
--- /dev/null
+++ b/src/main/java/com/institutosemprealerta/semprealerta/swagger/annotations/OkResponse.java
@@ -0,0 +1,15 @@
+package com.institutosemprealerta.semprealerta.swagger.annotations;
+
+import io.swagger.v3.oas.annotations.responses.ApiResponse;
+import org.springframework.http.HttpStatus;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Target({ElementType.METHOD, ElementType.TYPE})
+@Retention(RetentionPolicy.RUNTIME)
+@ApiResponse(responseCode = "200", description = "Requisição finalizada com sucesso", useReturnTypeSchema = true)
+public @interface OkResponse {
+}
diff --git a/src/main/java/com/institutosemprealerta/semprealerta/utils/DateManipulation.java b/src/main/java/com/institutosemprealerta/semprealerta/utils/DateManipulation.java
new file mode 100644
index 0000000..9a4e128
--- /dev/null
+++ b/src/main/java/com/institutosemprealerta/semprealerta/utils/DateManipulation.java
@@ -0,0 +1,16 @@
+package com.institutosemprealerta.semprealerta.utils;
+
+import java.time.LocalDate;
+import java.time.format.DateTimeFormatter;
+
+public abstract class DateManipulation {
+ public static LocalDate stringToLocalDate(String date) {
+ DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
+ return LocalDate.parse(date, formatter);
+ }
+
+ public static String localDateToString(LocalDate date) {
+ DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
+ return date.format(formatter);
+ }
+}
diff --git a/src/main/java/com/institutosemprealerta/semprealerta/utils/HashGeneration.java b/src/main/java/com/institutosemprealerta/semprealerta/utils/HashGeneration.java
new file mode 100644
index 0000000..a884f31
--- /dev/null
+++ b/src/main/java/com/institutosemprealerta/semprealerta/utils/HashGeneration.java
@@ -0,0 +1,10 @@
+package com.institutosemprealerta.semprealerta.utils;
+
+import java.util.HashSet;
+import java.util.Random;
+import java.util.Set;
+
+public abstract class HashGeneration {
+
+
+}
diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml
new file mode 100644
index 0000000..2bc41ea
--- /dev/null
+++ b/src/main/resources/application-dev.yml
@@ -0,0 +1,29 @@
+spring:
+ datasource:
+ url: jdbc:postgresql://localhost:5432/postgres?serverTimezone=UTC
+ username: postgres
+ password: 123
+ jpa:
+ hibernate:
+ ddl-auto: update
+ show-sql: true
+ servlet:
+ multipart:
+ max-file-size: 200MB
+ max-request-size: 215MB
+
+ flyway:
+ enabled: true
+ locations: classpath:db/migration
+ baseline-on-migrate: true
+ validate-on-migrate: false
+
+file:
+ upload-dir: pdf
+springdoc:
+ show-actuator: true
+api:
+ security:
+ token:
+ secret: ${SECRET:secret}
+
diff --git a/src/main/resources/application-prod.yml b/src/main/resources/application-prod.yml
new file mode 100644
index 0000000..e69de29
diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties
deleted file mode 100644
index 8b13789..0000000
--- a/src/main/resources/application.properties
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml
new file mode 100644
index 0000000..a1d742e
--- /dev/null
+++ b/src/main/resources/application.yml
@@ -0,0 +1,7 @@
+file:
+ upload-dir: pdf
+
+api:
+ security:
+ token:
+ secret: ${SECRET:secret}
\ No newline at end of file
diff --git a/src/main/resources/db/migration/V1__create-user-table.sql b/src/main/resources/db/migration/V1__create-user-table.sql
new file mode 100644
index 0000000..46d9da6
--- /dev/null
+++ b/src/main/resources/db/migration/V1__create-user-table.sql
@@ -0,0 +1,21 @@
+CREATE TABLE users
+(
+ id BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL,
+ registration VARCHAR(255),
+ name VARCHAR(255),
+ password VARCHAR(255),
+ gender VARCHAR(255),
+ birth_date date,
+ roles SMALLINT,
+ created_at TIMESTAMP WITHOUT TIME ZONE DEFAULT NOW(),
+ email VARCHAR(255),
+ phone VARCHAR(255),
+ street VARCHAR(255),
+ number VARCHAR(255),
+ city VARCHAR(255),
+ zip_code VARCHAR(255),
+ CONSTRAINT pk_users PRIMARY KEY (id)
+);
+
+ALTER TABLE users
+ ADD CONSTRAINT uc_users_registration UNIQUE (registration);
\ No newline at end of file
diff --git a/src/main/resources/db/migration/V2__create-file-table.sql b/src/main/resources/db/migration/V2__create-file-table.sql
new file mode 100644
index 0000000..fd6d482
--- /dev/null
+++ b/src/main/resources/db/migration/V2__create-file-table.sql
@@ -0,0 +1,9 @@
+CREATE TABLE files
+(
+ id BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL,
+ file_name VARCHAR(255),
+ file_download_uri VARCHAR(255),
+ file_type VARCHAR(255),
+ upload_date TIMESTAMP WITHOUT TIME ZONE,
+ CONSTRAINT pk_files PRIMARY KEY (id)
+);
\ No newline at end of file
diff --git a/src/main/resources/db/migration/V3__create-post-table.sql b/src/main/resources/db/migration/V3__create-post-table.sql
new file mode 100644
index 0000000..47d9049
--- /dev/null
+++ b/src/main/resources/db/migration/V3__create-post-table.sql
@@ -0,0 +1,13 @@
+CREATE TABLE post
+(
+ id BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL,
+ title VARCHAR(255) NOT NULL,
+ slug VARCHAR(255) NOT NULL,
+ content TEXT,
+ banner VARCHAR(255),
+ CONSTRAINT pk_post PRIMARY KEY (id)
+);
+
+
+ALTER TABLE post
+ ADD COLUMN created_at TIMESTAMP WITHOUT TIME ZONE NOT NULL;
diff --git a/src/test/java/com/institutosemprealerta/semprealerta/SempreAlertaApplicationTests.java b/src/test/java/com/institutosemprealerta/semprealerta/SempreAlertaApplicationTests.java
index aab2b73..aa4386b 100644
--- a/src/test/java/com/institutosemprealerta/semprealerta/SempreAlertaApplicationTests.java
+++ b/src/test/java/com/institutosemprealerta/semprealerta/SempreAlertaApplicationTests.java
@@ -1,9 +1,11 @@
package com.institutosemprealerta.semprealerta;
import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.boot.test.context.SpringBootTest;
-@SpringBootTest
+@ExtendWith(MockitoExtension.class)
class SempreAlertaApplicationTests {
@Test
diff --git a/src/test/java/com/institutosemprealerta/semprealerta/application/controllers/AuthenticationControllerTest.java b/src/test/java/com/institutosemprealerta/semprealerta/application/controllers/AuthenticationControllerTest.java
new file mode 100644
index 0000000..a0653a9
--- /dev/null
+++ b/src/test/java/com/institutosemprealerta/semprealerta/application/controllers/AuthenticationControllerTest.java
@@ -0,0 +1,66 @@
+package com.institutosemprealerta.semprealerta.application.controllers;
+
+import com.institutosemprealerta.semprealerta.domain.ports.out.exceptions.user.UserNotFoundException;
+import com.institutosemprealerta.semprealerta.domain.ports.out.request.LoginDTO;
+import com.institutosemprealerta.semprealerta.domain.ports.out.responses.LoginResponse;
+import com.institutosemprealerta.semprealerta.domain.service.AuthenticationService;
+import com.institutosemprealerta.semprealerta.infrastructure.entity.user.LoginFactory;
+import com.institutosemprealerta.semprealerta.infrastructure.entity.user.mocks.UserMocks;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.junit.jupiter.MockitoExtension;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.reset;
+import static org.mockito.Mockito.when;
+import static org.junit.jupiter.api.Assertions.*;
+
+@ExtendWith(MockitoExtension.class)
+@DisplayName("AuthenticationController")
+class AuthenticationControllerTest {
+
+ @InjectMocks
+ private AuthenticationController authenticationController;
+
+ @Mock
+ private AuthenticationService authenticationService;
+
+ private final LoginResponse token = LoginFactory.INSTANCE.createNewLoginResponse("this-is-the-way");
+ private final LoginDTO userCredentials = UserMocks.returnValidLoginDTO();
+
+ @BeforeEach
+ void setUp() {
+ when(authenticationService.login(any(LoginDTO.class)))
+ .thenReturn(token);
+ }
+
+ @AfterEach
+ void tearDown() {
+ reset(authenticationService);
+ }
+
+ @Test
+ @DisplayName("Should login successfully")
+ void should_Login_Successfully() {
+ ResponseEntity> loginResponse = authenticationController.login(userCredentials);
+
+ assertNotNull(loginResponse);
+ assertEquals(HttpStatus.OK, loginResponse.getStatusCode());
+ assertEquals(token, loginResponse.getBody());
+ }
+ @Test
+ @DisplayName("Should login with failure")
+ void should_Login_With_Failure() {
+ when(authenticationService.login(any(LoginDTO.class))).thenThrow(UserNotFoundException.class);
+
+ assertThrows(UserNotFoundException.class, () -> authenticationController.login(userCredentials));
+ }
+
+}
\ No newline at end of file
diff --git a/src/test/java/com/institutosemprealerta/semprealerta/application/handler/GlobalExceptionHandlerTest.java b/src/test/java/com/institutosemprealerta/semprealerta/application/handler/GlobalExceptionHandlerTest.java
new file mode 100644
index 0000000..27cd5a8
--- /dev/null
+++ b/src/test/java/com/institutosemprealerta/semprealerta/application/handler/GlobalExceptionHandlerTest.java
@@ -0,0 +1,90 @@
+package com.institutosemprealerta.semprealerta.application.handler;
+
+import com.institutosemprealerta.semprealerta.domain.ports.out.exceptions.ExceptionPattern;
+import com.institutosemprealerta.semprealerta.domain.ports.out.exceptions.file.FileNotFoundException;
+import com.institutosemprealerta.semprealerta.domain.ports.out.exceptions.file.InvalidFileException;
+import com.institutosemprealerta.semprealerta.domain.ports.out.exceptions.post.PostNotFoundException;
+import com.institutosemprealerta.semprealerta.domain.ports.out.exceptions.user.EmailAlreadyExistsException;
+import com.institutosemprealerta.semprealerta.domain.ports.out.exceptions.user.UserNotFoundException;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.InjectMocks;
+import org.mockito.junit.jupiter.MockitoExtension;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+
+import java.util.Objects;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+@ExtendWith(MockitoExtension.class)
+@DisplayName("GlobalExceptionHandler")
+class GlobalExceptionHandlerTest {
+
+ @InjectMocks
+ private GlobalExceptionHandler globalExceptionHandler;
+
+
+ @Test
+ @DisplayName("Should handler with user not found exception")
+ void should_HandlerUserNotFoundException() {
+ UserNotFoundException exception = new UserNotFoundException("User not found");
+ ResponseEntity response = globalExceptionHandler.handlerUserNotFoundException(exception);
+
+ assertEquals(HttpStatus.NOT_FOUND, response.getStatusCode());
+ assertNotNull(response);
+ assertEquals(exception.getMessage(), Objects.requireNonNull(response.getBody()).getDetails());
+ assertEquals(exception.getClass().getName(), Objects.requireNonNull(response.getBody()).getDeveloperMessage());
+ }
+
+ @Test
+ @DisplayName("Should handler with email already exists exception")
+ void should_HandlerEmailAlreadyExistsException() {
+ EmailAlreadyExistsException exception = new EmailAlreadyExistsException("user email already exists");
+ ResponseEntity response = globalExceptionHandler.handlerEmailAlreadyExistsException(exception);
+
+ assertNotNull(response);
+ assertEquals(HttpStatus.CONFLICT, response.getStatusCode());
+ assertEquals(exception.getMessage(), Objects.requireNonNull(response.getBody()).getDetails());
+ assertEquals(exception.getClass().getName(), Objects.requireNonNull(response.getBody()).getDeveloperMessage());
+ }
+
+ @Test
+ @DisplayName("Should handler with post not found exception")
+ void should_HandlerPostNotFoundException() {
+ PostNotFoundException exception = new PostNotFoundException("Post not found");
+ ResponseEntity response = globalExceptionHandler.handlerPostNotFoundException(exception);
+
+ assertNotNull(response);
+ assertEquals(HttpStatus.NOT_FOUND, response.getStatusCode());
+ assertEquals(exception.getMessage(), Objects.requireNonNull(response.getBody()).getDetails());
+ assertEquals(exception.getClass().getName(), Objects.requireNonNull(response.getBody()).getDeveloperMessage());
+ }
+
+ @Test
+ @DisplayName("Should handler with file not found exception")
+ void should_HandlerFileNotFoundException() {
+ FileNotFoundException exception = new FileNotFoundException("File not found");
+ ResponseEntity response = globalExceptionHandler.handlerFileNotFoundException(exception);
+
+ assertNotNull(response);
+ assertEquals(HttpStatus.NOT_FOUND, response.getStatusCode());
+ assertEquals(exception.getMessage(), Objects.requireNonNull(response.getBody()).getDetails());
+ assertEquals(exception.getClass().getName(), Objects.requireNonNull(response.getBody()).getDeveloperMessage());
+ }
+
+ @Test
+ @DisplayName("Should handler with invalid file exception")
+ void should_HandlerInvalidFileException() {
+ InvalidFileException exception = new InvalidFileException("File type invalid");
+ ResponseEntity response = globalExceptionHandler.handlerInvalidFileException(exception);
+
+ assertNotNull(response);
+ assertEquals(HttpStatus.BAD_REQUEST, response.getStatusCode());
+ assertEquals(exception.getMessage(), Objects.requireNonNull(response.getBody()).getDetails());
+ assertEquals(exception.getClass().getName(), Objects.requireNonNull(response.getBody()).getDeveloperMessage());
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/com/institutosemprealerta/semprealerta/application/service/impl/PostServiceImplTest.java b/src/test/java/com/institutosemprealerta/semprealerta/application/service/impl/PostServiceImplTest.java
new file mode 100644
index 0000000..bda6f87
--- /dev/null
+++ b/src/test/java/com/institutosemprealerta/semprealerta/application/service/impl/PostServiceImplTest.java
@@ -0,0 +1,129 @@
+package com.institutosemprealerta.semprealerta.application.service.impl;
+
+import com.institutosemprealerta.semprealerta.domain.model.Post;
+import com.institutosemprealerta.semprealerta.domain.ports.in.SlugGenerator;
+import com.institutosemprealerta.semprealerta.domain.ports.out.PostRepository;
+import com.institutosemprealerta.semprealerta.domain.service.impl.PostServiceImpl;
+import com.institutosemprealerta.semprealerta.infrastructure.entity.post.mocks.PostMocks;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.junit.jupiter.MockitoExtension;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.PageImpl;
+import org.springframework.data.domain.PageRequest;
+import org.springframework.data.domain.Pageable;
+
+import java.util.List;
+
+import static org.junit.jupiter.api.Assertions.*;
+import static org.mockito.ArgumentMatchers.*;
+import static org.mockito.Mockito.*;
+
+@ExtendWith(MockitoExtension.class)
+@DisplayName("Post Service Test")
+class PostServiceImplTest {
+
+ @InjectMocks
+ private PostServiceImpl postService;
+
+ @Mock
+ private PostRepository postRepository;
+
+ @Mock
+ private SlugGenerator slugGenerator;
+
+ private final Post postMock = PostMocks.returnValidPostModel();
+
+ @BeforeEach
+ void setUp() {
+ List posts = List.of(postMock);
+
+ Pageable pageable = PageRequest.of(0, 10);
+ Page postPage = new PageImpl<>(posts, pageable, posts.size());
+
+ when(postService.listAll(any(Pageable.class))).thenReturn(postPage);
+ when(postRepository.save(any(Post.class))).thenReturn(postMock.getSlug());
+ when(postRepository.findBySlug(anyString())).thenReturn(postMock);
+ when(postRepository.findById(anyLong())).thenReturn(postMock);
+ doNothing().when(postRepository).delete(anyLong());
+ doNothing().when(postRepository).update(anyLong(), any(Post.class));
+
+ when(slugGenerator.generate(anyString())).thenReturn(postMock.getSlug());
+ }
+
+ @AfterEach
+ void tearDown() {
+ reset(postRepository, slugGenerator);
+ }
+
+ @Test
+ @DisplayName("Should save a post successfully")
+ void should_SaveAPost_Successfully() {
+ Post postToCreate = PostMocks.returnValidPostModelToBeCreated();
+ String slug = postService.save(postToCreate);
+
+ assertNotNull(slug);
+ assertEquals(postToCreate.getSlug(), slug);
+ verify(slugGenerator, times(1)).generate(postToCreate.getTitle());
+ }
+
+ @Test
+ @DisplayName("Should delete a post successfully")
+ void should_DeleteAPost_Successfully() {
+ assertDoesNotThrow(() -> postService.delete(postMock.getId()));
+ verify(postRepository, times(1)).delete(postMock.getId());
+ }
+
+ @Test
+ @DisplayName("Should update a post successfully")
+ void should_UpdateAPost_Successfully() {
+ Post postToUpdate = PostMocks.returnValidPostModelToBeUpdated();
+
+ assertDoesNotThrow(() -> postService.update(postMock.getId(), postToUpdate));
+ verify(postRepository, times(1)).update(postMock.getId(), postToUpdate);
+ verify(slugGenerator, times(1)).generate(postToUpdate.getTitle());
+ }
+
+ @Test
+ @DisplayName("Should list all pageable successfully")
+ void should_ListAllPageable_Successfully() {
+ PageRequest pageable = PageRequest.of(0, 10);
+
+ Page posts = postService.listAll(pageable);
+
+ assertNotNull(posts);
+ assertEquals(1, posts.getTotalElements());
+ assertEquals(postMock.getId(), posts.getContent().get(0).getId());
+ }
+
+ @Test
+ @DisplayName("Should find by slug successfully")
+ void should_FindBySlug_Successfully() {
+ Post post = postService.findBySlug(postMock.getSlug());
+
+ assertNotNull(post);
+ assertEquals(postMock.getId(), post.getId());
+ assertEquals(postMock.getTitle(), post.getTitle());
+ assertEquals(postMock.getSlug(), post.getSlug());
+ assertEquals(postMock.getContent(), post.getContent());
+ assertEquals(postMock.getBanner(), post.getBanner());
+ }
+
+ @Test
+ @DisplayName("Should find by id successfully")
+ void should_FindById_Successfully() {
+ Post post = postService.findById(postMock.getId());
+
+ assertNotNull(post);
+ assertEquals(postMock.getId(), post.getId());
+ assertEquals(postMock.getTitle(), post.getTitle());
+ assertEquals(postMock.getSlug(), post.getSlug());
+ assertEquals(postMock.getContent(), post.getContent());
+ assertEquals(postMock.getBanner(), post.getBanner());
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/com/institutosemprealerta/semprealerta/application/service/impl/StorageServiceImplTest.java b/src/test/java/com/institutosemprealerta/semprealerta/application/service/impl/StorageServiceImplTest.java
new file mode 100644
index 0000000..f38d343
--- /dev/null
+++ b/src/test/java/com/institutosemprealerta/semprealerta/application/service/impl/StorageServiceImplTest.java
@@ -0,0 +1,149 @@
+package com.institutosemprealerta.semprealerta.application.service.impl;
+
+import com.institutosemprealerta.semprealerta.domain.model.File;
+import com.institutosemprealerta.semprealerta.domain.ports.out.FileRepository;
+import com.institutosemprealerta.semprealerta.domain.ports.out.responses.FileResponse;
+import com.institutosemprealerta.semprealerta.domain.service.impl.StorageServiceImpl;
+import com.institutosemprealerta.semprealerta.infrastructure.config.FileStorageProperties;
+import com.institutosemprealerta.semprealerta.infrastructure.entity.file.mocks.FileMocks;
+import org.junit.jupiter.api.*;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.Mock;
+import org.mockito.junit.jupiter.MockitoExtension;
+import org.springframework.core.io.Resource;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.io.IOException;
+import java.nio.file.*;
+import java.nio.file.spi.FileSystemProvider;
+import java.util.List;
+
+import static org.junit.jupiter.api.Assertions.*;
+import static org.mockito.Mockito.*;
+
+@ExtendWith(MockitoExtension.class)
+class StorageServiceImplTest {
+
+ private StorageServiceImpl storageService;
+
+ @Mock
+ private FileRepository fileRepository;
+
+ @Mock
+ private FileStorageProperties fileStorageProperties;
+
+ @Mock
+ private MultipartFile mockFile;
+
+ @Mock
+ private FileSystem mockFileSystem;
+
+ @Mock
+ private FileSystemProvider mockFileSystemProvider;
+
+ private final FileResponse fileResponse = FileMocks.returnValidFileResponse();
+
+ @BeforeEach
+ void setUp() throws IOException {
+
+ when(fileStorageProperties.getUploadDir()).thenReturn("pdf");
+ storageService = new StorageServiceImpl(fileStorageProperties, fileRepository);
+
+ when(mockFile.getOriginalFilename()).thenReturn("file.txt");
+ when(mockFile.isEmpty()).thenReturn(false);
+ when(mockFile.getSize()).thenReturn(100L);
+ when(mockFile.getContentType()).thenReturn("text/plain");
+
+
+ Path pathToDirectory = Paths.get("pdf");
+ Path pathToFile = Paths.get("pdf/file.txt");
+ if (!Files.exists(pathToDirectory)) {
+ Files.createDirectories(pathToDirectory);
+ }
+ if (!Files.exists(pathToFile)) {
+ Files.createFile(pathToFile);
+ }
+
+ when(mockFileSystem.provider()).thenReturn(mockFileSystemProvider);
+
+
+ when(fileRepository.listAll()).thenReturn(List.of(fileResponse));
+ doNothing().when(fileRepository).save(any(File.class));
+
+ }
+
+ @AfterEach
+ void tearDown() {
+ reset(
+ fileRepository,
+ fileStorageProperties,
+ mockFile,
+ mockFileSystem,
+ mockFileSystemProvider
+ );
+ }
+
+ @AfterAll
+ static void afterAll() {
+ Path pathToFile = Paths.get("pdf/file.txt");
+ try {
+ Files.deleteIfExists(pathToFile);
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ @Test
+ void init() {
+ }
+
+ @Test
+ @DisplayName("Should Store File With Valid Name")
+ void should_Store_File_With_ValidName() {
+ String fileName = storageService.store(mockFile, "text/plain");
+
+ assertNotNull(fileName);
+ assertEquals("file.txt", fileName);
+ verify(fileRepository, times(1)).save(any(File.class));
+ }
+
+ @Test
+ @DisplayName("should load file path")
+ void should_Load_File_Path() {
+ assertDoesNotThrow(() -> storageService.load("file.txt"));
+ }
+
+ @Test
+ @DisplayName("Should Load All Files Successfully")
+ void should_LoadAll_Files_Successfully() throws IOException {
+ List allFiles = storageService.loadAll();
+
+ assertNotNull(allFiles);
+ assertEquals(1, allFiles.size());
+ assertEquals(fileResponse.fileName(), allFiles.get(0).fileName());
+ verify(fileRepository, times(1)).listAll();
+ }
+
+ @Test
+ @DisplayName("Should Load File Successfully")
+ void should_loadAsResource_Successfully() {
+ String fileName = "file.txt";
+
+ Resource response = storageService.loadAsResource(fileName);
+
+ assertNotNull(response);
+ }
+
+ @Test
+ @DisplayName("Should Load File As Resource Successfully")
+ void should_Delete_A_Resource() {
+ String fileName = fileResponse.fileName();
+ assertDoesNotThrow(() -> storageService.delete(fileName));
+
+ }
+
+ @Test
+ @DisplayName("Should Delete File Successfully")
+ void should_DeleteAll_Successfully() {
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/com/institutosemprealerta/semprealerta/application/service/impl/UserServiceImplTest.java b/src/test/java/com/institutosemprealerta/semprealerta/application/service/impl/UserServiceImplTest.java
new file mode 100644
index 0000000..c80629c
--- /dev/null
+++ b/src/test/java/com/institutosemprealerta/semprealerta/application/service/impl/UserServiceImplTest.java
@@ -0,0 +1,100 @@
+package com.institutosemprealerta.semprealerta.application.service.impl;
+
+import com.institutosemprealerta.semprealerta.domain.ports.out.UserRepository;
+import com.institutosemprealerta.semprealerta.domain.service.impl.UserServiceImpl;
+import com.institutosemprealerta.semprealerta.infrastructure.entity.user.User;
+import com.institutosemprealerta.semprealerta.infrastructure.entity.user.mocks.UserMocks;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.ArgumentMatchers;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.junit.jupiter.MockitoExtension;
+
+import java.util.Optional;
+
+import static org.junit.jupiter.api.Assertions.*;
+import static org.mockito.Mockito.*;
+
+@ExtendWith(MockitoExtension.class)
+class UserServiceImplTest {
+
+ @InjectMocks
+ private UserServiceImpl userService;
+
+ @Mock
+ private UserRepository userRepository;
+
+ @BeforeEach
+ void setUp() {
+ User userValid = UserMocks.returnValidUserEntity();
+
+ lenient().when(userRepository.findById(ArgumentMatchers.anyInt())).thenReturn(Optional.of(userValid));
+ lenient().when(userRepository.findByRegistration(ArgumentMatchers.anyString())).thenReturn(Optional.of(userValid));
+ lenient().when(userRepository.findByEmail(ArgumentMatchers.anyString())).thenReturn(Optional.of(userValid));
+ lenient().doNothing().when(userRepository).save(ArgumentMatchers.any(User.class));
+ lenient().doNothing().when(userRepository).update(ArgumentMatchers.anyInt(), ArgumentMatchers.any(User.class));
+ lenient().doNothing().when(userRepository).delete(ArgumentMatchers.anyInt());
+ }
+
+ @AfterEach
+ void tearDown() {
+ reset(userRepository);
+ }
+
+ @Test
+ @DisplayName("Should Save User Successfully")
+ void should_Save_User_Successfully() {
+ User userToCreate = UserMocks.returnValidUserToCreate();
+ assertDoesNotThrow(() -> userService.save(userToCreate));
+ }
+
+ @Test
+ @DisplayName("Should Update User Successfully")
+ void should_update_User_Successfully() {
+ User userToUpdate = UserMocks.returnValidUserToUpdate();
+ assertDoesNotThrow(() -> userService.update(1, userToUpdate));
+ }
+
+ @Test
+ @DisplayName("Should Delete User Successfully")
+ void should_Delete_User_Successfully() {
+ assertDoesNotThrow(() -> userService.delete(1));
+ }
+
+ @Test
+ @DisplayName("Should Find User By Registration Successfully")
+ void should_findUserByRegistration_Successfully() {
+ User expectedUser = UserMocks.returnValidUserEntity();
+ User userFound = userService.findByRegistration(expectedUser.getRegistration());
+
+ assertEquals(expectedUser.getRegistration(), userFound.getRegistration());
+ assertEquals(expectedUser.getName(), userFound.getName());
+ assertNotNull(userFound.getId());
+ }
+
+ @Test
+ @DisplayName("Should Find User By Email Successfully")
+ void should_findUserByEmail_Successfully() {
+ User expectedUser = UserMocks.returnValidUserEntity();
+ User userFound = userService.findByEmail(expectedUser.getContact().getEmail());
+
+ assertEquals(expectedUser.getContact().getEmail(), userFound.getContact().getEmail());
+ assertEquals(expectedUser.getName(), userFound.getName());
+ assertNotNull(userFound.getId());
+ }
+
+ @Test
+ @DisplayName("Should Find User By Id Successfully")
+ void should_findUserById_Successfully() {
+ User expectedUser = UserMocks.returnValidUserEntity();
+ User userFound = userService.findById(1);
+
+ assertEquals(expectedUser.getRegistration(), userFound.getRegistration());
+ assertEquals(expectedUser.getName(), userFound.getName());
+ assertNotNull(userFound.getId());
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/com/institutosemprealerta/semprealerta/domain/ports/in/impl/SlugifySlugGeneratorTest.java b/src/test/java/com/institutosemprealerta/semprealerta/domain/ports/in/impl/SlugifySlugGeneratorTest.java
new file mode 100644
index 0000000..e48293b
--- /dev/null
+++ b/src/test/java/com/institutosemprealerta/semprealerta/domain/ports/in/impl/SlugifySlugGeneratorTest.java
@@ -0,0 +1,48 @@
+package com.institutosemprealerta.semprealerta.domain.ports.in.impl;
+
+import com.github.slugify.Slugify;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.junit.jupiter.MockitoExtension;
+import org.springframework.data.util.ReflectionUtils;
+
+import static org.junit.jupiter.api.Assertions.*;
+import static org.mockito.Mockito.reset;
+import static org.mockito.Mockito.when;
+
+@ExtendWith(MockitoExtension.class)
+@DisplayName("Slugify slug generator test")
+class SlugifySlugGeneratorTest {
+
+ @InjectMocks
+ private SlugifySlugGenerator slugifySlugGenerator;
+
+ @Mock
+ Slugify slugify;
+
+ @BeforeEach
+ void setUp() {
+
+ }
+
+ @AfterEach
+ void turnDown() {
+ reset(slugify);
+ }
+
+ @Test
+ @DisplayName("Should generate slug successfully")
+ void should_GenerateSlug_Successfully() {
+ String input = "Test Input";
+ String expectedSlug = "test-input";
+ when(slugify.slugify(input)).thenReturn(expectedSlug);
+
+ String result = slugifySlugGenerator.generate(input);
+ assertEquals(expectedSlug, result);
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/com/institutosemprealerta/semprealerta/domain/service/impl/AuthenticationServiceImplTest.java b/src/test/java/com/institutosemprealerta/semprealerta/domain/service/impl/AuthenticationServiceImplTest.java
new file mode 100644
index 0000000..4cf8545
--- /dev/null
+++ b/src/test/java/com/institutosemprealerta/semprealerta/domain/service/impl/AuthenticationServiceImplTest.java
@@ -0,0 +1,69 @@
+package com.institutosemprealerta.semprealerta.domain.service.impl;
+
+import com.institutosemprealerta.semprealerta.domain.ports.out.request.LoginDTO;
+import com.institutosemprealerta.semprealerta.domain.ports.out.responses.LoginResponse;
+import com.institutosemprealerta.semprealerta.domain.service.TokenService;
+import com.institutosemprealerta.semprealerta.infrastructure.entity.user.Contact;
+import com.institutosemprealerta.semprealerta.infrastructure.entity.user.User;
+import com.institutosemprealerta.semprealerta.infrastructure.entity.user.mocks.UserMocks;
+import org.springframework.security.core.Authentication;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.junit.jupiter.MockitoExtension;
+import org.springframework.security.authentication.AuthenticationManager;
+import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
+
+
+import static org.junit.jupiter.api.Assertions.*;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.reset;
+import static org.mockito.Mockito.when;
+
+@ExtendWith(MockitoExtension.class)
+@DisplayName("Authentication service")
+class AuthenticationServiceImplTest {
+
+ @InjectMocks
+ private AuthenticationServiceImpl authenticationService;
+
+ @Mock
+ private AuthenticationManager authenticationManager;
+
+ @Mock
+ private TokenService tokenService;
+
+ private final Contact contact = UserMocks.returnValidContact();
+ private LoginDTO loginDTO;
+
+ private final String token = "mockToken";
+
+ @BeforeEach
+ void setUp() {
+ loginDTO = new LoginDTO(contact.getEmail(), "123");
+ User user = new User();
+ user.setContact(contact);
+
+ UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(user, null);
+ when(authenticationManager.authenticate(any(Authentication.class))).thenReturn(authentication);
+
+
+ when(tokenService.generateToken(any(User.class))).thenReturn(token);
+
+ }
+
+ @AfterEach
+ void tearDown() {
+ reset(tokenService, authenticationManager);
+ }
+
+ @Test
+ void login() {
+ LoginResponse response = authenticationService.login(loginDTO);
+ assertEquals(token, response.accessToken());
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/com/institutosemprealerta/semprealerta/domain/service/impl/AuthorizationServiceTest.java b/src/test/java/com/institutosemprealerta/semprealerta/domain/service/impl/AuthorizationServiceTest.java
new file mode 100644
index 0000000..cba3a4c
--- /dev/null
+++ b/src/test/java/com/institutosemprealerta/semprealerta/domain/service/impl/AuthorizationServiceTest.java
@@ -0,0 +1,51 @@
+package com.institutosemprealerta.semprealerta.domain.service.impl;
+
+import com.institutosemprealerta.semprealerta.domain.service.UserService;
+import com.institutosemprealerta.semprealerta.infrastructure.entity.user.User;
+import com.institutosemprealerta.semprealerta.infrastructure.entity.user.mocks.UserMocks;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.junit.jupiter.MockitoExtension;
+import org.springframework.security.core.userdetails.UserDetails;
+
+import static org.junit.jupiter.api.Assertions.*;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.reset;
+import static org.mockito.Mockito.when;
+
+@ExtendWith(MockitoExtension.class)
+@DisplayName("Authorization Service")
+class AuthorizationServiceTest {
+
+ @InjectMocks
+ private AuthorizationService authorizationService;
+
+ @Mock
+ private UserService userService;
+
+ private final User validUserEntity = UserMocks.returnValidUserEntity();
+
+ @BeforeEach
+ void setUp() {
+ when(userService.findByEmail(anyString()))
+ .thenReturn(validUserEntity);
+ }
+
+ @AfterEach
+ void tearDown() {
+ reset(userService);
+ }
+
+ @Test
+ @DisplayName("Should load user by username successfully")
+ void should_LoadUserByUsername_Successfully() {
+ UserDetails response = authorizationService.loadUserByUsername(validUserEntity.getContact().getEmail());
+
+ assertNotNull(response);
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/com/institutosemprealerta/semprealerta/domain/service/impl/TokenServiceImplTest.java b/src/test/java/com/institutosemprealerta/semprealerta/domain/service/impl/TokenServiceImplTest.java
new file mode 100644
index 0000000..c30aff4
--- /dev/null
+++ b/src/test/java/com/institutosemprealerta/semprealerta/domain/service/impl/TokenServiceImplTest.java
@@ -0,0 +1,81 @@
+package com.institutosemprealerta.semprealerta.domain.service.impl;
+
+import com.auth0.jwt.JWT;
+import com.auth0.jwt.algorithms.Algorithm;
+import com.auth0.jwt.exceptions.JWTCreationException;
+import com.institutosemprealerta.semprealerta.infrastructure.entity.user.Contact;
+import com.institutosemprealerta.semprealerta.infrastructure.entity.user.User;
+import com.institutosemprealerta.semprealerta.infrastructure.entity.user.mocks.UserMocks;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.junit.jupiter.MockitoExtension;
+import org.springframework.test.util.ReflectionTestUtils;
+
+import java.util.Date;
+
+import static org.junit.jupiter.api.Assertions.*;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.reset;
+import static org.mockito.Mockito.when;
+
+@ExtendWith(MockitoExtension.class)
+@DisplayName("Token service")
+class TokenServiceImplTest {
+
+ @InjectMocks
+ private TokenServiceImpl tokenService;
+
+ @Mock
+ User user;
+
+ @Mock
+ Contact contact;
+
+ private final String secret = "secret";
+
+ @BeforeEach
+ void setUp() {
+ ReflectionTestUtils.setField(tokenService, "secret", secret);
+
+ when(user.getContact()).thenReturn(contact);
+ when(user.getContact().getEmail())
+ .thenReturn(UserMocks.returnValidContact().getEmail());
+ }
+
+ @AfterEach
+ void turnDown() {
+ reset(user, contact);
+ }
+
+ @Test
+ @DisplayName("Should generate token successfully")
+ void should_GenerateToken_Successfully() {
+ String token = tokenService.generateToken(user);
+
+ assertNotNull(token);
+ }
+
+ @Test
+ @DisplayName("Should validate token successfully")
+ void should_ValidateToken_Successfully() {
+ String token = tokenService.generateToken(user);
+ String subject = tokenService.validateToken(token);
+
+ assertEquals(user.getContact().getEmail(), subject);
+ }
+
+ @Test
+ @DisplayName("Should validate token with failure")
+ void should_ValidateToken_With_Failure() {
+ String invalidToken = "where are you now?";
+ String invalidSubject = tokenService.validateToken(invalidToken);
+
+ assertTrue(invalidSubject.isBlank());
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/com/institutosemprealerta/semprealerta/infrastructure/adpters/JpaFileRepositoryAdapterTest.java b/src/test/java/com/institutosemprealerta/semprealerta/infrastructure/adpters/JpaFileRepositoryAdapterTest.java
new file mode 100644
index 0000000..5bf3ffe
--- /dev/null
+++ b/src/test/java/com/institutosemprealerta/semprealerta/infrastructure/adpters/JpaFileRepositoryAdapterTest.java
@@ -0,0 +1,71 @@
+package com.institutosemprealerta.semprealerta.infrastructure.adpters;
+
+import com.institutosemprealerta.semprealerta.domain.model.File;
+import com.institutosemprealerta.semprealerta.domain.ports.out.responses.FileResponse;
+import com.institutosemprealerta.semprealerta.infrastructure.entity.file.FileEntity;
+import com.institutosemprealerta.semprealerta.infrastructure.entity.file.FileEntityFactory;
+import com.institutosemprealerta.semprealerta.infrastructure.entity.file.mocks.FileMocks;
+import com.institutosemprealerta.semprealerta.infrastructure.repositories.JpaFileRepository;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.ArgumentMatchers;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.junit.jupiter.MockitoExtension;
+
+import java.util.List;
+
+import static org.junit.jupiter.api.Assertions.*;
+import static org.mockito.Mockito.*;
+
+@ExtendWith(MockitoExtension.class)
+class JpaFileRepositoryAdapterTest {
+
+ @InjectMocks
+ private JpaFileRepositoryAdapter jpaFileRepositoryAdapter;
+
+ @Mock
+ private JpaFileRepository jpaFileRepository;
+
+ private final FileEntity validFile = FileEntityFactory.INSTANCE.create(
+ "file.txt",
+ "http://localhost:8080/api/v1/files/download/1",
+ "text/plain"
+ );
+
+ @BeforeEach
+ void setUp() {
+
+ when(jpaFileRepository.save(ArgumentMatchers.any(FileEntity.class))).thenReturn(validFile);
+ when(jpaFileRepository.findAll()).thenReturn(List.of(validFile));
+ doNothing().when(jpaFileRepository).deleteById(ArgumentMatchers.anyLong());
+ }
+
+ @AfterEach
+ void tearDown() {
+ reset(jpaFileRepository);
+ }
+
+ @Test
+ void save() {
+ File fileToCreate = FileMocks.createFile();
+ assertDoesNotThrow(() -> jpaFileRepositoryAdapter.save(fileToCreate));
+ }
+
+ @Test
+ void delete() {
+ assertDoesNotThrow(() -> jpaFileRepositoryAdapter.delete(1L));
+ }
+
+ @Test
+ void listAll() {
+ validFile.setId(1L);
+ List fileResponses = jpaFileRepositoryAdapter.listAll();
+
+ assertNotNull(fileResponses);
+ assertFalse(fileResponses.isEmpty());
+ assertEquals(validFile.getId(), fileResponses.get(0).id());
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/com/institutosemprealerta/semprealerta/infrastructure/adpters/JpaPostRepositoryAdapterTest.java b/src/test/java/com/institutosemprealerta/semprealerta/infrastructure/adpters/JpaPostRepositoryAdapterTest.java
new file mode 100644
index 0000000..88f0c72
--- /dev/null
+++ b/src/test/java/com/institutosemprealerta/semprealerta/infrastructure/adpters/JpaPostRepositoryAdapterTest.java
@@ -0,0 +1,118 @@
+package com.institutosemprealerta.semprealerta.infrastructure.adpters;
+
+import com.institutosemprealerta.semprealerta.domain.model.Post;
+import com.institutosemprealerta.semprealerta.infrastructure.entity.post.PostEntity;
+import com.institutosemprealerta.semprealerta.infrastructure.entity.post.mocks.PostMocks;
+import com.institutosemprealerta.semprealerta.infrastructure.repositories.JpaPostRepository;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.junit.jupiter.MockitoExtension;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.PageImpl;
+import org.springframework.data.domain.PageRequest;
+import org.springframework.data.domain.Pageable;
+
+import java.util.List;
+
+import static org.junit.jupiter.api.Assertions.*;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.*;
+
+@ExtendWith(MockitoExtension.class)
+@DisplayName("JpaPostRepositoryAdapterTest")
+class JpaPostRepositoryAdapterTest {
+
+ @InjectMocks
+ private JpaPostRepositoryAdapter jpaPostRepositoryAdapter;
+
+ @Mock
+ private JpaPostRepository jpaPostRepository;
+
+ private final PostEntity postMocks = PostMocks.returnValidPostEntity();
+
+ @BeforeEach
+ void setUp() {
+ List postEntityList = List.of(postMocks);
+
+ Pageable pageable = PageRequest.of(0, 10);
+ Page postEntityPage = new PageImpl<>(postEntityList, pageable, postEntityList.size());
+
+ when(jpaPostRepository.findAll(any(Pageable.class))).thenReturn(postEntityPage);
+ when(jpaPostRepository.save(any(PostEntity.class))).thenReturn(postMocks);
+ when(jpaPostRepository.findBySlug(any(String.class))).thenReturn(java.util.Optional.of(postMocks));
+ when(jpaPostRepository.findById(any(Long.class))).thenReturn(java.util.Optional.of(postMocks));
+ doNothing().when(jpaPostRepository).deleteById(any(Long.class));
+ }
+
+ @AfterEach
+ void tearDown() {
+ reset(jpaPostRepository);
+ }
+
+ @Test
+ @DisplayName("Should Save A Post Successfully")
+ void should_Save_A_Post_Successfully() {
+ PostEntity postEntity = PostMocks.returnValidPostToBeCreated();
+
+ String slug = jpaPostRepositoryAdapter.save(PostEntity.toModel(postEntity));
+
+ assertNotNull(slug);
+ assertEquals(postEntity.getSlug(), slug);
+ }
+
+ @Test
+ @DisplayName("Should Delete A Post Successfully")
+ void should_Delete_A_Post_Successfully() {
+ assertDoesNotThrow(() -> jpaPostRepositoryAdapter.delete(postMocks.getId()));
+ }
+
+ @Test
+ @DisplayName("Should Update A Post Successfully")
+ void should_Update_A_Post_Successfully() {
+ PostEntity postEntity = PostMocks.returnValidPostToBeUpdated();
+
+ assertDoesNotThrow(() -> jpaPostRepositoryAdapter.update(postMocks.getId(), PostEntity.toModel(postEntity)));
+ }
+
+ @Test
+ @DisplayName("Should ListAll PageablePost Successfully")
+ void should_ListAll_PageablePost_Successfully() {
+ PageRequest pageable = PageRequest.of(0, 10);
+ Page postPage = jpaPostRepositoryAdapter.listAll(pageable);
+
+ assertNotNull(postPage);
+ assertEquals(1, postPage.getTotalElements());
+ assertEquals(postMocks.getId(), postPage.getContent().get(0).getId());
+ }
+
+ @Test
+ @DisplayName("Should Find A PostBySlug Successfully")
+ void should_Find_A_PostBySlug_Successfully() {
+ Post post = jpaPostRepositoryAdapter.findBySlug(postMocks.getSlug());
+
+ assertNotNull(post);
+ assertEquals(postMocks.getId(), post.getId());
+ assertEquals(postMocks.getTitle(), post.getTitle());
+ assertEquals(postMocks.getSlug(), post.getSlug());
+ assertEquals(postMocks.getContent(), post.getContent());
+ assertEquals(postMocks.getBanner(), post.getBanner());
+ }
+
+ @Test
+ @DisplayName("Should Find A Post By Id Successfully")
+ void should_Find_A_Post_ById_Successfully() {
+ Post post = jpaPostRepositoryAdapter.findById(postMocks.getId());
+
+ assertNotNull(post);
+ assertEquals(postMocks.getId(), post.getId());
+ assertEquals(postMocks.getTitle(), post.getTitle());
+ assertEquals(postMocks.getSlug(), post.getSlug());
+ assertEquals(postMocks.getContent(), post.getContent());
+ assertEquals(postMocks.getBanner(), post.getBanner());
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/com/institutosemprealerta/semprealerta/infrastructure/adpters/JpaUserRepositoryAdapterTest.java b/src/test/java/com/institutosemprealerta/semprealerta/infrastructure/adpters/JpaUserRepositoryAdapterTest.java
new file mode 100644
index 0000000..e43c962
--- /dev/null
+++ b/src/test/java/com/institutosemprealerta/semprealerta/infrastructure/adpters/JpaUserRepositoryAdapterTest.java
@@ -0,0 +1,109 @@
+package com.institutosemprealerta.semprealerta.infrastructure.adpters;
+
+import com.institutosemprealerta.semprealerta.infrastructure.entity.user.User;
+import com.institutosemprealerta.semprealerta.infrastructure.entity.user.mocks.UserMocks;
+import com.institutosemprealerta.semprealerta.infrastructure.repositories.JpaUserRepository;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.ArgumentMatchers;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.junit.jupiter.MockitoExtension;
+
+import java.util.Optional;
+
+import static org.junit.jupiter.api.Assertions.*;
+import static org.mockito.Mockito.lenient;
+import static org.mockito.Mockito.reset;
+
+@ExtendWith(MockitoExtension.class)
+@DisplayName("JpaUserRepositoryAdapter")
+class JpaUserRepositoryAdapterTest {
+
+ @InjectMocks
+ private JpaUserRepositoryAdapter jpaUserRepositoryAdapter;
+
+ @Mock
+ private JpaUserRepository userRepository;
+
+
+ @BeforeEach
+ void setUp() {
+ User userValid = UserMocks.returnValidUserEntity();
+
+ lenient().when(userRepository.findById(ArgumentMatchers.anyInt())).thenReturn(Optional.of(userValid));
+ lenient().when(userRepository.findByRegistration(ArgumentMatchers.anyString())).thenReturn(Optional.of(userValid));
+ lenient().when(userRepository.findByEmail(ArgumentMatchers.anyString())).thenReturn(Optional.of(userValid));
+ lenient().when(userRepository.save(ArgumentMatchers.any(User.class))).thenReturn(userValid);
+ lenient().doNothing().when(userRepository).delete(ArgumentMatchers.any(User.class));
+ }
+
+ @AfterEach
+ void tearDown() {
+ reset(userRepository);
+ }
+
+ @Test
+ @DisplayName("Should Save User Successfully")
+ void should_Save_UserSuccessfully() {
+ User userToCreate = UserMocks.returnValidUserToCreate();
+ assertDoesNotThrow(() -> jpaUserRepositoryAdapter.save(userToCreate));
+ }
+
+ @Test
+ @DisplayName("Should Find User By Id Successfully")
+ void should_findUserById_Successfully() {
+ User expectedUser = UserMocks.returnValidUserEntity();
+
+ User user = jpaUserRepositoryAdapter.findById(1).orElse(new User());
+
+ assertNotNull(user);
+ assertEquals(expectedUser.getId(), user.getId());
+ assertEquals(expectedUser.getRegistration(), user.getRegistration());
+ assertEquals(expectedUser.getName(), user.getName());
+
+ }
+
+ @Test
+ @DisplayName("Should Update A User Successfully")
+ void should_Update_A_User_Successfully() {
+ User userToUpdate = UserMocks.returnValidUserToUpdate();
+ assertDoesNotThrow(() -> jpaUserRepositoryAdapter.update(1, userToUpdate));
+ }
+
+ @Test
+ @DisplayName("Should Delete A User Successfully")
+ void should_Delete_A_User_Successfully() {
+ assertDoesNotThrow(() -> jpaUserRepositoryAdapter.delete(1));
+ }
+
+ @Test
+ @DisplayName("Should Find User By Registration Successfully")
+ void should_findUserByRegistration_Successfully() {
+ User expectedUser = UserMocks.returnValidUserEntity();
+ String expectedRegistration = expectedUser.getRegistration();
+ User userFound = jpaUserRepositoryAdapter.findByRegistration(expectedRegistration).orElse(new User());
+
+ assertNotNull(userFound);
+ assertEquals(expectedRegistration, userFound.getRegistration());
+ assertEquals(expectedUser.getName(), userFound.getName());
+ assertNotNull(userFound.getId());
+ }
+
+ @Test
+ @DisplayName("Should Find User By Email Successfully")
+ void should_findUserByEmail_Successfully() {
+
+ User expectedUser = UserMocks.returnValidUserEntity();
+ String expectedEmail = expectedUser.getContact().getEmail();
+ User userFound = jpaUserRepositoryAdapter.findByEmail(expectedEmail).orElse(new User());
+
+ assertNotNull(userFound);
+ assertEquals(expectedEmail, userFound.getContact().getEmail());
+ assertEquals(expectedUser.getName(), userFound.getName());
+ assertNotNull(userFound.getId());
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/com/institutosemprealerta/semprealerta/infrastructure/controllers/FilesStorageControllerTest.java b/src/test/java/com/institutosemprealerta/semprealerta/infrastructure/controllers/FilesStorageControllerTest.java
new file mode 100644
index 0000000..73a3e28
--- /dev/null
+++ b/src/test/java/com/institutosemprealerta/semprealerta/infrastructure/controllers/FilesStorageControllerTest.java
@@ -0,0 +1,111 @@
+package com.institutosemprealerta.semprealerta.infrastructure.controllers;
+
+import com.institutosemprealerta.semprealerta.application.controllers.FilesStorageController;
+import com.institutosemprealerta.semprealerta.domain.service.StorageService;
+import jakarta.servlet.http.HttpServletRequest;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.junit.jupiter.MockitoExtension;
+import org.springframework.core.io.Resource;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.mock.web.MockHttpServletRequest;
+import org.springframework.mock.web.MockHttpServletResponse;
+import org.springframework.mock.web.MockMultipartFile;
+import org.springframework.web.context.request.RequestContextHolder;
+import org.springframework.web.context.request.ServletRequestAttributes;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+
+import static org.junit.jupiter.api.Assertions.*;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.reset;
+import static org.mockito.Mockito.when;
+
+@ExtendWith(MockitoExtension.class)
+class FilesStorageControllerTest {
+
+ @InjectMocks
+ FilesStorageController filesStorageController;
+
+ @Mock
+ StorageService storageService;
+
+ @Mock
+ Resource mockResource;
+
+ @Mock
+ HttpServletRequest mockRequest;
+
+
+ private final MultipartFile mockFile = new MockMultipartFile("file.txt", "content".getBytes());
+
+ @BeforeEach
+ void setUp() throws IOException {
+ String contentFile = "Hello, World!";
+ InputStream is = new ByteArrayInputStream(contentFile.getBytes(StandardCharsets.UTF_8));
+ when(mockResource.getInputStream()).thenReturn(is);
+
+ when(mockResource.getFilename()).thenReturn("file.txt");
+ when(storageService.store(any(), any())).thenReturn("file.txt");
+
+ Path tempFile = Files.createTempFile("temp", ".txt");
+ File file = tempFile.toFile();
+ when(mockResource.getFile()).thenReturn(file);
+
+ when(storageService.loadAsResource(any())).thenReturn(mockResource);
+ }
+
+ @AfterEach
+ void tearDown() {
+ reset(storageService, mockResource);
+ }
+
+ @Test
+ @DisplayName("Should upload file successfully")
+ void should_UploadFile_Successfully() {
+ MockHttpServletRequest request = new MockHttpServletRequest();
+ MockHttpServletResponse response = new MockHttpServletResponse();
+
+ ServletRequestAttributes sra = new ServletRequestAttributes(request, response);
+ RequestContextHolder.setRequestAttributes(sra);
+
+ String fileType = "pdf";
+ String expected = "File uploaded successfully, file name: file.txt on path: http://localhost/api/v1/files/download/file.txt";
+ ResponseEntity responseEntity = filesStorageController.uploadFile(mockFile, fileType);
+
+ assertTrue(responseEntity.getStatusCode().is2xxSuccessful());
+ assertEquals(HttpStatus.CREATED, responseEntity.getStatusCode());
+ assertEquals(expected, responseEntity.getBody());
+ }
+
+ @Test
+ @DisplayName("Should download file successfully")
+ void should_DownloadFile_Successfully() {
+ MockHttpServletRequest request = new MockHttpServletRequest();
+
+ ResponseEntity response = filesStorageController.downloadFile("file.txt", request);
+
+ assertTrue(response.getStatusCode().is2xxSuccessful());
+ assertEquals(HttpStatus.OK, response.getStatusCode());
+ assertEquals("attachment; filename=\"file.txt\"", response.getHeaders().get(HttpHeaders.CONTENT_DISPOSITION).get(0));
+ }
+
+ @Test
+ @DisplayName("Should list files successfully")
+ void should_ListFiles_Successfully() {
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/com/institutosemprealerta/semprealerta/infrastructure/controllers/PostControllerTest.java b/src/test/java/com/institutosemprealerta/semprealerta/infrastructure/controllers/PostControllerTest.java
new file mode 100644
index 0000000..6eaaec8
--- /dev/null
+++ b/src/test/java/com/institutosemprealerta/semprealerta/infrastructure/controllers/PostControllerTest.java
@@ -0,0 +1,110 @@
+package com.institutosemprealerta.semprealerta.infrastructure.controllers;
+
+import com.institutosemprealerta.semprealerta.application.controllers.PostController;
+import com.institutosemprealerta.semprealerta.domain.service.PostService;
+import com.institutosemprealerta.semprealerta.domain.model.Post;
+import com.institutosemprealerta.semprealerta.infrastructure.entity.post.mocks.PostMocks;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.junit.jupiter.MockitoExtension;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.PageImpl;
+import org.springframework.data.domain.PageRequest;
+import org.springframework.data.domain.Pageable;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+
+import java.util.List;
+import java.util.Objects;
+
+import static org.junit.jupiter.api.Assertions.*;
+import static org.mockito.Mockito.*;
+
+@ExtendWith(MockitoExtension.class)
+@DisplayName("Given a PostController")
+class PostControllerTest {
+
+ @InjectMocks
+ private PostController postController;
+
+ @Mock
+ private PostService postService;
+
+ private final Post postMock = PostMocks.returnValidPostModel();
+
+ @BeforeEach
+ void setUp() {
+ List posts = List.of(postMock);
+
+ Pageable pageable = PageRequest.of(0, 10);
+ Page postPage = new PageImpl<>(posts, pageable, posts.size());
+
+ when(postService.listAll(pageable)).thenReturn(postPage);
+ when(postService.save(postMock)).thenReturn(postMock.getSlug());
+ when(postService.findBySlug(postMock.getSlug())).thenReturn(postMock);
+ doNothing().when(postService).update(postMock.getId(), postMock);
+ doNothing().when(postService).delete(postMock.getId());
+ }
+
+ @AfterEach
+ void tearDown() {
+ reset(postService);
+ }
+
+ @Test
+ @DisplayName("When getAllPosts, then return a pageable list of posts")
+ void should_GetAllPosts_Successfully() {
+ PageRequest pageable = PageRequest.of(0, 10);
+ ResponseEntity> postPage = postController.getAllPosts(pageable);
+
+ assertNotNull(postPage);
+ assertEquals(HttpStatus.OK, postPage.getStatusCode());
+ assertEquals(1, Objects.requireNonNull(postPage.getBody()).getTotalElements());
+ assertEquals(postMock, postPage.getBody().getContent().get(0));
+ }
+
+ @Test
+ @DisplayName("When createPost, then return a URI")
+ void should_CreatePost_Successfully() {
+ ResponseEntity> response = postController.createPost(postMock);
+
+ assertNotNull(response);
+ assertEquals(HttpStatus.CREATED, response.getStatusCode());
+ assertEquals("/api/v1/posts/" + postMock.getSlug(), response.getHeaders().getLocation().getPath());
+ }
+
+ @Test
+ @DisplayName("When getPostBySlug, then return a post")
+ void should_GetPostBySlug_Successfully() {
+ ResponseEntity response = postController.getPostBySlug(postMock.getSlug());
+
+ assertNotNull(response);
+ assertEquals(HttpStatus.OK, response.getStatusCode());
+ assertEquals(postMock, response.getBody());
+ }
+
+ @Test
+ @DisplayName("When updatePost, then return no content")
+ void should_UpdatePost_Successfully() {
+ ResponseEntity> response = postController.updatePost(postMock.getId(), postMock);
+
+ assertNotNull(response);
+ assertEquals(HttpStatus.NO_CONTENT, response.getStatusCode());
+ verify(postService, times(1)).update(postMock.getId(), postMock);
+ }
+
+ @Test
+ @DisplayName("When deletePost, then return no content")
+ void should_DeletePost_Successfully() {
+ ResponseEntity> response = postController.deletePost(postMock.getId());
+
+ assertNotNull(response);
+ assertEquals(HttpStatus.NO_CONTENT, response.getStatusCode());
+ verify(postService, times(1)).delete(postMock.getId());
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/com/institutosemprealerta/semprealerta/infrastructure/controllers/UserControllerTest.java b/src/test/java/com/institutosemprealerta/semprealerta/infrastructure/controllers/UserControllerTest.java
new file mode 100644
index 0000000..50faac5
--- /dev/null
+++ b/src/test/java/com/institutosemprealerta/semprealerta/infrastructure/controllers/UserControllerTest.java
@@ -0,0 +1,114 @@
+package com.institutosemprealerta.semprealerta.infrastructure.controllers;
+
+import com.institutosemprealerta.semprealerta.application.controllers.UserController;
+import com.institutosemprealerta.semprealerta.domain.service.UserService;
+import com.institutosemprealerta.semprealerta.domain.model.UserDTO;
+import com.institutosemprealerta.semprealerta.domain.ports.out.responses.UserResponse;
+import com.institutosemprealerta.semprealerta.infrastructure.entity.user.User;
+import com.institutosemprealerta.semprealerta.infrastructure.entity.user.mocks.UserMocks;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.ArgumentMatchers;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.junit.jupiter.MockitoExtension;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+
+import java.util.Objects;
+
+import static org.mockito.Mockito.*;
+import static org.junit.jupiter.api.Assertions.*;
+
+@ExtendWith(MockitoExtension.class)
+@DisplayName("User Controller")
+class UserControllerTest {
+
+ @InjectMocks
+ private UserController userController;
+
+ @Mock
+ private UserService userService;
+
+ @BeforeEach
+ void setUp() {
+ User validUser = UserMocks.returnValidUserEntity();
+
+ lenient().doNothing().when(userService).save(ArgumentMatchers.any(User.class));
+ lenient().when(userService.findById(ArgumentMatchers.anyInt())).thenReturn(validUser);
+ lenient().when(userService.findByRegistration(ArgumentMatchers.anyString())).thenReturn(validUser);
+ lenient().doNothing().when(userService).update(ArgumentMatchers.anyInt(), ArgumentMatchers.any(User.class));
+ lenient().doNothing().when(userService).delete(ArgumentMatchers.anyInt());
+
+ }
+
+ @AfterEach
+ void tearDown() {
+ reset(userService);
+ }
+
+ @Test
+ @DisplayName("Should create user successfully")
+ void should_CreateUser_Successfully() {
+ UserDTO userDTO = UserMocks.returnValidUserDTO();
+
+ ResponseEntity> response = userController.createUser(userDTO);
+
+ assertNotNull(response);
+ assertTrue(response.getStatusCode().is2xxSuccessful());
+ assertEquals(HttpStatus.CREATED.value(), response.getStatusCode().value());
+ assertFalse(response.hasBody());
+ }
+
+ @Test
+ @DisplayName("Should find user by id successfully")
+ void should_FindUserById_Successfully() {
+ ResponseEntity response = userController.findById(1);
+ User expectedUser = UserMocks.returnValidUserEntity();
+
+ assertTrue(response.getStatusCode().is2xxSuccessful());
+ assertTrue(response.hasBody());
+ assertEquals(HttpStatus.OK.value(), response.getStatusCode().value());
+ assertEquals(expectedUser.getName(), Objects.requireNonNull(response.getBody()).name());
+ }
+
+ @Test
+ @DisplayName("Should find user by registration successfully")
+ void should_findByUserRegistration_Successfully() {
+ User expectedUser = UserMocks.returnValidUserEntity();
+ String expectedRegistration = expectedUser.getRegistration();
+
+ ResponseEntity response = userController.findByRegistration(expectedRegistration);
+
+ assertTrue(response.getStatusCode().is2xxSuccessful());
+ assertEquals(HttpStatus.OK.value(), response.getStatusCode().value());
+ assertTrue(response.hasBody());
+ assertEquals(expectedUser.getName(), Objects.requireNonNull(response.getBody()).name());
+ }
+
+ @Test
+ @DisplayName("Should update user successfully")
+ void should_updateUser_Successfully() {
+ UserDTO userDTO = UserMocks.returnValidUserDTO();
+ ResponseEntity> response = userController.updateUser(1, userDTO);
+
+ assertNotNull(response);
+ assertTrue(response.getStatusCode().is2xxSuccessful());
+ assertEquals(HttpStatus.NO_CONTENT.value(), response.getStatusCode().value());
+ assertFalse(response.hasBody());
+ }
+
+ @Test
+ @DisplayName("Should delete user successfully")
+ void should_deleteUser_Successfully() {
+ ResponseEntity> response = userController.deleteUser(1);
+
+ assertNotNull(response);
+ assertTrue(response.getStatusCode().is2xxSuccessful());
+ assertEquals(HttpStatus.NO_CONTENT.value(), response.getStatusCode().value());
+ assertFalse(response.hasBody());
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/com/institutosemprealerta/semprealerta/infrastructure/entity/file/FileEntityFactory.java b/src/test/java/com/institutosemprealerta/semprealerta/infrastructure/entity/file/FileEntityFactory.java
new file mode 100644
index 0000000..a3d2303
--- /dev/null
+++ b/src/test/java/com/institutosemprealerta/semprealerta/infrastructure/entity/file/FileEntityFactory.java
@@ -0,0 +1,26 @@
+package com.institutosemprealerta.semprealerta.infrastructure.entity.file;
+
+import com.institutosemprealerta.semprealerta.domain.model.File;
+
+public class FileEntityFactory {
+ public static final FileEntityFactory INSTANCE = new FileEntityFactory();
+
+ private FileEntityFactory() {
+ }
+
+ public FileEntity create(File file) {
+ return new FileEntity(file.getFileName(), file.getFileDownloadUri(), file.getFileType());
+ }
+
+ public FileEntity create(
+ String fileName,
+ String fileDownloadUri,
+ String fileType
+ ) {
+ return new FileEntity(fileName, fileDownloadUri, fileType);
+ }
+
+ public FileEntity create() {
+ return new FileEntity();
+ }
+}
diff --git a/src/test/java/com/institutosemprealerta/semprealerta/infrastructure/entity/file/mocks/FileMocks.java b/src/test/java/com/institutosemprealerta/semprealerta/infrastructure/entity/file/mocks/FileMocks.java
new file mode 100644
index 0000000..9ff7602
--- /dev/null
+++ b/src/test/java/com/institutosemprealerta/semprealerta/infrastructure/entity/file/mocks/FileMocks.java
@@ -0,0 +1,25 @@
+package com.institutosemprealerta.semprealerta.infrastructure.entity.file.mocks;
+
+import com.institutosemprealerta.semprealerta.domain.model.File;
+import com.institutosemprealerta.semprealerta.domain.ports.out.responses.FileResponse;
+import com.institutosemprealerta.semprealerta.infrastructure.entity.file.FileEntity;
+
+import java.time.LocalDateTime;
+
+public class FileMocks {
+ public static FileEntity createFileEntity() {
+ return new FileEntity("fileName", "fileDownloadUri", "fileType");
+ }
+
+ public static File createFile() {
+ return File.builder()
+ .fileName("fileName")
+ .fileDownloadUri("fileDownloadUri")
+ .fileType("fileType")
+ .build();
+ }
+
+ public static FileResponse returnValidFileResponse() {
+ return new FileResponse(1L, "file.txt", "/api/v1/download/1", "fileType", LocalDateTime.now());
+ }
+}
diff --git a/src/test/java/com/institutosemprealerta/semprealerta/infrastructure/entity/post/PostEntityFactory.java b/src/test/java/com/institutosemprealerta/semprealerta/infrastructure/entity/post/PostEntityFactory.java
new file mode 100644
index 0000000..5af5cec
--- /dev/null
+++ b/src/test/java/com/institutosemprealerta/semprealerta/infrastructure/entity/post/PostEntityFactory.java
@@ -0,0 +1,48 @@
+package com.institutosemprealerta.semprealerta.infrastructure.entity.post;
+
+import java.time.LocalDateTime;
+
+public class PostEntityFactory {
+ public static PostEntityFactory INSTANCE = new PostEntityFactory();
+
+ private PostEntityFactory() {
+ }
+
+ public PostEntity createPostEntity() {
+ return new PostEntity();
+ }
+
+ public PostEntity createPostEntity(
+ String title,
+ String slug,
+ String content,
+ String banner
+ ) {
+ return new PostEntity(
+ title,
+ slug,
+ content,
+ banner
+ );
+ }
+
+ public PostEntity createPostEntity(
+ Long id,
+ String title,
+ String slug,
+ String content,
+ String banner,
+ LocalDateTime createdAt
+ ) {
+ return new PostEntity(
+ id,
+ title,
+ slug,
+ content,
+ banner,
+ createdAt
+ );
+ }
+
+
+}
diff --git a/src/test/java/com/institutosemprealerta/semprealerta/infrastructure/entity/post/mocks/PostMocks.java b/src/test/java/com/institutosemprealerta/semprealerta/infrastructure/entity/post/mocks/PostMocks.java
new file mode 100644
index 0000000..83cd1bb
--- /dev/null
+++ b/src/test/java/com/institutosemprealerta/semprealerta/infrastructure/entity/post/mocks/PostMocks.java
@@ -0,0 +1,83 @@
+package com.institutosemprealerta.semprealerta.infrastructure.entity.post.mocks;
+
+import com.github.javafaker.Faker;
+import com.institutosemprealerta.semprealerta.domain.model.Post;
+import com.institutosemprealerta.semprealerta.infrastructure.entity.post.PostEntity;
+import com.institutosemprealerta.semprealerta.infrastructure.entity.post.PostEntityFactory;
+
+import java.time.LocalDateTime;
+
+public class PostMocks {
+ private static final Faker faker = new Faker();
+
+ private static final Long id = faker.number().randomNumber();
+ private static final String title = faker.lorem().sentence();
+ private static final String slug = faker.internet().slug();
+ private static final String content = faker.lorem().paragraph();
+ private static final String banner = faker.internet().image();
+ private static final LocalDateTime createdAt = LocalDateTime.now();
+
+ public static PostEntity returnValidPostEntity() {
+ return PostEntityFactory.INSTANCE.createPostEntity(
+ id,
+ title,
+ slug,
+ content,
+ banner,
+ createdAt
+ );
+ }
+
+ public static PostEntity returnValidPostToBeCreated() {
+ return PostEntityFactory.INSTANCE.createPostEntity(
+ title,
+ slug,
+ content,
+ banner
+ );
+ }
+
+ public static PostEntity returnValidPostToBeUpdated() {
+ return PostEntityFactory.INSTANCE.createPostEntity(
+ id,
+ title,
+ slug,
+ faker.dune().saying(),
+ banner,
+ createdAt
+ );
+ }
+
+ public static Post returnValidPostModel() {
+ return new Post(
+ id,
+ title,
+ slug,
+ content,
+ banner,
+ createdAt
+ );
+ }
+
+ public static Post returnValidPostModelToBeCreated() {
+ return new Post(
+ null,
+ title,
+ slug,
+ content,
+ banner,
+ null
+ );
+ }
+
+ public static Post returnValidPostModelToBeUpdated() {
+ return new Post(
+ id,
+ title,
+ slug,
+ faker.dune().saying(),
+ banner,
+ createdAt
+ );
+ }
+}
diff --git a/src/test/java/com/institutosemprealerta/semprealerta/infrastructure/entity/user/ContactFactory.java b/src/test/java/com/institutosemprealerta/semprealerta/infrastructure/entity/user/ContactFactory.java
new file mode 100644
index 0000000..d2b227e
--- /dev/null
+++ b/src/test/java/com/institutosemprealerta/semprealerta/infrastructure/entity/user/ContactFactory.java
@@ -0,0 +1,16 @@
+package com.institutosemprealerta.semprealerta.infrastructure.entity.user;
+
+public class ContactFactory {
+ public static final ContactFactory INSTANCE = new ContactFactory();
+
+ private ContactFactory() {
+ }
+
+ public Contact newContact() {
+ return new Contact();
+ }
+
+ public Contact newContact(String email, String phone) {
+ return new Contact(email, phone);
+ }
+}
diff --git a/src/test/java/com/institutosemprealerta/semprealerta/infrastructure/entity/user/LoginFactory.java b/src/test/java/com/institutosemprealerta/semprealerta/infrastructure/entity/user/LoginFactory.java
new file mode 100644
index 0000000..1d04c44
--- /dev/null
+++ b/src/test/java/com/institutosemprealerta/semprealerta/infrastructure/entity/user/LoginFactory.java
@@ -0,0 +1,18 @@
+package com.institutosemprealerta.semprealerta.infrastructure.entity.user;
+
+import com.institutosemprealerta.semprealerta.domain.ports.out.request.LoginDTO;
+import com.institutosemprealerta.semprealerta.domain.ports.out.responses.LoginResponse;
+
+public class LoginFactory {
+ public static final LoginFactory INSTANCE = new LoginFactory();
+
+ private LoginFactory() {}
+
+ public LoginResponse createNewLoginResponse(String token) {
+ return new LoginResponse(token);
+ }
+
+ public LoginDTO createNewLoginDTO(String email, String password) {
+ return new LoginDTO(email, password);
+ }
+}
diff --git a/src/test/java/com/institutosemprealerta/semprealerta/infrastructure/entity/user/UserEntityFactory.java b/src/test/java/com/institutosemprealerta/semprealerta/infrastructure/entity/user/UserEntityFactory.java
new file mode 100644
index 0000000..c83382c
--- /dev/null
+++ b/src/test/java/com/institutosemprealerta/semprealerta/infrastructure/entity/user/UserEntityFactory.java
@@ -0,0 +1,31 @@
+package com.institutosemprealerta.semprealerta.infrastructure.entity.user;
+
+import java.time.LocalDate;
+
+public class UserEntityFactory {
+ public static final UserEntityFactory INSTANCE = new UserEntityFactory();
+
+ private UserEntityFactory() {
+ }
+
+ public User newUser() {
+ return new User();
+ }
+
+ public User newUser(
+ String name,
+ String password,
+ String gender,
+ LocalDate birthday,
+ UserRoles userRoles,
+ String email,
+ String phone,
+ Address address
+ ) {
+ Contact contact = ContactFactory.INSTANCE.newContact(email, phone);
+
+ return new User(name, password, gender, birthday, userRoles, contact, address);
+ }
+
+
+}
diff --git a/src/test/java/com/institutosemprealerta/semprealerta/infrastructure/entity/user/mocks/UserMocks.java b/src/test/java/com/institutosemprealerta/semprealerta/infrastructure/entity/user/mocks/UserMocks.java
new file mode 100644
index 0000000..ddd84e5
--- /dev/null
+++ b/src/test/java/com/institutosemprealerta/semprealerta/infrastructure/entity/user/mocks/UserMocks.java
@@ -0,0 +1,74 @@
+package com.institutosemprealerta.semprealerta.infrastructure.entity.user.mocks;
+
+import com.institutosemprealerta.semprealerta.domain.model.UserDTO;
+import com.institutosemprealerta.semprealerta.domain.ports.out.request.LoginDTO;
+import com.institutosemprealerta.semprealerta.infrastructure.entity.user.*;
+
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+
+public class UserMocks {
+ public static User returnValidUserEntity() {
+ User user = UserEntityFactory.INSTANCE.newUser();
+
+ LocalDate birthDate = LocalDate.of(1990, 1, 1);
+
+ user.setId(1L);
+ user.setRegistration("123456");
+ user.setName("John Doe");
+ user.setBirthDate(birthDate);
+ user.setGender("M");
+ user.setContact(returnValidContact());
+ user.setPassword("123456");
+ user.setAddress(returnValidAddress());
+ user.setRoles(UserRoles.USER);
+ user.setCreatedAt(LocalDateTime.now());
+
+ return user;
+ }
+
+ public static User returnValidUserToCreate() {
+ User user = returnValidUserEntity();
+ user.setId(null);
+ return user;
+ }
+
+ public static User returnValidUserToUpdate() {
+ User user = returnValidUserEntity();
+ user.setRegistration("654321");
+ return user;
+ }
+
+ public static Contact returnValidContact() {
+ return ContactFactory.INSTANCE.newContact("user@email.com", "123456789");
+ }
+
+ public static Address returnValidAddress() {
+ return new Address("Street", "123", "NY", "123546");
+ }
+
+
+ public static UserDTO returnValidUserDTO() {
+ User user = returnValidUserEntity();
+ return new UserDTO(
+ user.getName(),
+ user.getContact().getEmail(),
+ user.getPassword(),
+ user.getContact().getPhone(),
+ user.getGender(),
+ user.getBirthDate(),
+ user.getRoles(),
+ user.getAddress().getStreet(),
+ user.getAddress().getNumber(),
+ user.getAddress().getCity(),
+ user.getAddress().getZipCode()
+ );
+ }
+
+ public static LoginDTO returnValidLoginDTO() {
+ return LoginFactory.INSTANCE.createNewLoginDTO(
+ "user@email.com",
+ "1234"
+ );
+ }
+}
diff --git a/src/test/java/com/institutosemprealerta/semprealerta/infrastructure/repositories/JpaFileRepositoryTest.java b/src/test/java/com/institutosemprealerta/semprealerta/infrastructure/repositories/JpaFileRepositoryTest.java
new file mode 100644
index 0000000..c81d418
--- /dev/null
+++ b/src/test/java/com/institutosemprealerta/semprealerta/infrastructure/repositories/JpaFileRepositoryTest.java
@@ -0,0 +1,49 @@
+package com.institutosemprealerta.semprealerta.infrastructure.repositories;
+
+import com.institutosemprealerta.semprealerta.infrastructure.entity.file.FileEntity;
+import com.institutosemprealerta.semprealerta.infrastructure.entity.file.mocks.FileMocks;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+import org.mockito.InjectMocks;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+@DataJpaTest
+@DisplayName("JpaFileRepositoryTest")
+class JpaFileRepositoryTest {
+
+ @Autowired
+ private JpaFileRepository jpaFileRepository;
+
+
+ @AfterEach
+ void tearDown() {
+ this.jpaFileRepository.deleteAll();
+ }
+
+ @Test
+ @DisplayName("Should save file data to database")
+ void should_save_file_data_to_database() {
+
+ FileEntity fileToCreate = FileMocks.createFileEntity();
+ FileEntity fileCreated = this.jpaFileRepository.save(fileToCreate);
+
+ assertNotNull(fileCreated);
+ assertEquals(fileToCreate.getFileName(), fileCreated.getFileName());
+ assertEquals(fileToCreate.getFileDownloadUri(), fileCreated.getFileDownloadUri());
+ assertEquals(fileToCreate.getFileType(), fileCreated.getFileType());
+ }
+
+ @Test
+ @DisplayName("Should delete file by file id")
+ void should_delete_file_by_file_id() {
+ FileEntity fileToCreate = FileMocks.createFileEntity();
+ FileEntity fileCreated = this.jpaFileRepository.save(fileToCreate);
+
+ assertDoesNotThrow(() -> this.jpaFileRepository.deleteById(fileCreated.getId()));
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/com/institutosemprealerta/semprealerta/infrastructure/repositories/JpaPostRepositoryTest.java b/src/test/java/com/institutosemprealerta/semprealerta/infrastructure/repositories/JpaPostRepositoryTest.java
new file mode 100644
index 0000000..fe8c085
--- /dev/null
+++ b/src/test/java/com/institutosemprealerta/semprealerta/infrastructure/repositories/JpaPostRepositoryTest.java
@@ -0,0 +1,49 @@
+package com.institutosemprealerta.semprealerta.infrastructure.repositories;
+
+import com.institutosemprealerta.semprealerta.infrastructure.entity.post.PostEntity;
+import com.institutosemprealerta.semprealerta.infrastructure.entity.post.PostEntityFactory;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+@DataJpaTest
+@DisplayName("JpaPostRepositoryTest")
+class JpaPostRepositoryTest {
+
+ @Autowired
+ private JpaPostRepository jpaPostRepository;
+
+ private final PostEntity postToCreate = PostEntityFactory.INSTANCE.createPostEntity(
+ "title",
+ "slug",
+ "content",
+ "banner"
+ );
+
+ @BeforeEach
+ void setUp() {
+ this.jpaPostRepository.save(postToCreate);
+ }
+
+ @AfterEach
+ void tearDown() {
+ this.jpaPostRepository.deleteAll();
+ }
+
+ @Test
+ @DisplayName("Should find post by slug")
+ void should_find_post_by_slug() {
+ PostEntity postFound = this.jpaPostRepository.findBySlug("slug").orElse(null);
+
+ assertNotNull(postFound);
+ assertEquals(postToCreate.getTitle(), postFound.getTitle());
+ assertEquals(postToCreate.getSlug(), postFound.getSlug());
+ assertEquals(postToCreate.getContent(), postFound.getContent());
+ assertEquals(postToCreate.getBanner(), postFound.getBanner());
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/com/institutosemprealerta/semprealerta/infrastructure/repositories/JpaUserRepositoryTest.java b/src/test/java/com/institutosemprealerta/semprealerta/infrastructure/repositories/JpaUserRepositoryTest.java
new file mode 100644
index 0000000..4b1cfcd
--- /dev/null
+++ b/src/test/java/com/institutosemprealerta/semprealerta/infrastructure/repositories/JpaUserRepositoryTest.java
@@ -0,0 +1,69 @@
+package com.institutosemprealerta.semprealerta.infrastructure.repositories;
+
+import com.institutosemprealerta.semprealerta.infrastructure.entity.user.User;
+import com.institutosemprealerta.semprealerta.infrastructure.entity.user.UserEntityFactory;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
+
+import java.time.LocalDate;
+import java.util.Optional;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+@DataJpaTest
+@DisplayName("Tests for JpaUserRepository")
+class JpaUserRepositoryTest {
+
+ @Autowired
+ private JpaUserRepository jpaUserRepository;
+
+ @BeforeEach
+ void setUp() {
+ User userToCreate = UserEntityFactory.INSTANCE.newUser(
+ "Teste",
+ "123456",
+ "M",
+ LocalDate.now(),
+ null,
+ "user@email.com",
+ "123456",
+ null
+ );
+ this.jpaUserRepository.save(userToCreate);
+ }
+
+ @AfterEach
+ void tearDown() {
+ this.jpaUserRepository.deleteAll();
+ }
+
+ @Test
+ void findByEmail() {
+ Optional userFound = this.jpaUserRepository.findByEmail("user@email.com");
+ LocalDate now = LocalDate.now();
+
+ assertTrue(userFound.isPresent());
+ assertNotNull(userFound.get().getId());
+ assertEquals("Teste", userFound.get().getName());
+ assertEquals("123456", userFound.get().getPassword());
+ assertEquals("M", userFound.get().getGender());
+ assertEquals(now, userFound.get().getBirthDate());
+
+ }
+
+ @Test
+ void findByRegistration() {
+ Optional userFound = this.jpaUserRepository.findByEmail("user@email.com");
+
+ userFound.ifPresent(user -> {
+ Optional userByRegistration = this.jpaUserRepository.findByRegistration(user.getRegistration());
+ assertTrue(userByRegistration.isPresent());
+ assertEquals(user, userByRegistration.get());
+ assertNotNull(userByRegistration.get().getId());
+ });
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/com/institutosemprealerta/semprealerta/wrapper/PageableResponse.java b/src/test/java/com/institutosemprealerta/semprealerta/wrapper/PageableResponse.java
new file mode 100644
index 0000000..2820e19
--- /dev/null
+++ b/src/test/java/com/institutosemprealerta/semprealerta/wrapper/PageableResponse.java
@@ -0,0 +1,42 @@
+package com.institutosemprealerta.semprealerta.wrapper;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.databind.JsonNode;
+import lombok.Getter;
+import lombok.Setter;
+import org.springframework.data.domain.PageImpl;
+import org.springframework.data.domain.PageRequest;
+
+import java.util.List;
+
+import static com.fasterxml.jackson.annotation.JsonCreator.Mode.PROPERTIES;
+
+@Getter
+@Setter
+public class PageableResponse extends PageImpl {
+ private boolean first;
+ private boolean last;
+ private int totalPages;
+ private int numberOfElements;
+
+ @JsonCreator(mode = PROPERTIES )
+ public PageableResponse(@JsonProperty("content") List content,
+ @JsonProperty("number") int number,
+ @JsonProperty("size") int size,
+ @JsonProperty("totalElements") int totalElements,
+ @JsonProperty("last") boolean last,
+ @JsonProperty("first") boolean first,
+ @JsonProperty("totalPages") int totalPages,
+ @JsonProperty("numberOfElements") int numberOfElements,
+ @JsonProperty("pageable") JsonNode pageable,
+ @JsonProperty("sort") JsonNode sort) {
+ super(content, PageRequest.of(number, size), totalElements);
+
+ this.last = last;
+ this.first = first;
+ this.totalPages = totalPages;
+ this.numberOfElements = numberOfElements;
+
+ }
+}
\ No newline at end of file