From ba2d941f59cc4eea7b1296b8f9dd8dfc3c261ea1 Mon Sep 17 00:00:00 2001 From: MatheusVict Date: Mon, 4 Mar 2024 12:54:56 -0300 Subject: [PATCH 1/9] feat: add swagger plugin Signed-off-by: MatheusVict --- pom.xml | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/pom.xml b/pom.xml index 91204cd..7eb5268 100644 --- a/pom.xml +++ b/pom.xml @@ -15,6 +15,7 @@ sempre-alerta 17 + 2.3.0 @@ -37,6 +38,16 @@ org.springframework.boot spring-boot-starter-web + + 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 From 65ee5c963e4930e9405d3130206111ff21994ebc Mon Sep 17 00:00:00 2001 From: MatheusVict Date: Mon, 4 Mar 2024 13:40:24 -0300 Subject: [PATCH 2/9] feat: swagger custom response annotations Signed-off-by: MatheusVict --- .../controllers/FilesStorageController.java | 9 +++++++-- .../swagger/annotations/ConflictResponse.java | 18 ++++++++++++++++++ .../swagger/annotations/CreatedResponse.java | 14 ++++++++++++++ .../swagger/annotations/NoContentResponse.java | 14 ++++++++++++++ .../swagger/annotations/NotFoundResponse.java | 18 ++++++++++++++++++ .../swagger/annotations/OkResponse.java | 15 +++++++++++++++ src/main/resources/application-dev.yml | 2 ++ 7 files changed, 88 insertions(+), 2 deletions(-) create mode 100644 src/main/java/com/institutosemprealerta/semprealerta/swagger/annotations/ConflictResponse.java create mode 100644 src/main/java/com/institutosemprealerta/semprealerta/swagger/annotations/CreatedResponse.java create mode 100644 src/main/java/com/institutosemprealerta/semprealerta/swagger/annotations/NoContentResponse.java create mode 100644 src/main/java/com/institutosemprealerta/semprealerta/swagger/annotations/NotFoundResponse.java create mode 100644 src/main/java/com/institutosemprealerta/semprealerta/swagger/annotations/OkResponse.java diff --git a/src/main/java/com/institutosemprealerta/semprealerta/application/controllers/FilesStorageController.java b/src/main/java/com/institutosemprealerta/semprealerta/application/controllers/FilesStorageController.java index 0a6e3d6..0d90555 100644 --- a/src/main/java/com/institutosemprealerta/semprealerta/application/controllers/FilesStorageController.java +++ b/src/main/java/com/institutosemprealerta/semprealerta/application/controllers/FilesStorageController.java @@ -2,6 +2,8 @@ import com.institutosemprealerta.semprealerta.domain.service.StorageService; import com.institutosemprealerta.semprealerta.domain.ports.out.responses.FileResponse; +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; @@ -17,6 +19,7 @@ @Controller @RequestMapping("/api/v1/files") +@Tag(name = "Files", description = "Files management") public class FilesStorageController { private StorageService storageService; @@ -24,8 +27,9 @@ public FilesStorageController(StorageService storageService) { this.storageService = storageService; } - @PostMapping("/upload") - public ResponseEntity uploadFile(@RequestParam("file") MultipartFile file, @RequestParam("file_type") String fileType) { + @Operation(summary = "Upload a file", description = "Upload a file to the server") + @PostMapping(value = "/upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) + public ResponseEntity uploadFile(@RequestPart("file") MultipartFile file, @RequestParam("file_type") String fileType) { String fileName = storageService.store(file, fileType); @@ -39,6 +43,7 @@ public ResponseEntity uploadFile(@RequestParam("file") MultipartFile fil @GetMapping("/download/{fileName:.+}") @ResponseBody + @Operation(summary = "Download a file", description = "Download a file from the server") public ResponseEntity downloadFile( @PathVariable String fileName, HttpServletRequest request 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..80d47d5 --- /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 = "There are some conflicts", + 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..1a72b8f --- /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 = "Created Successfully", 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..77d52e5 --- /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 = "Request finished successfully without content", 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..6418927 --- /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 = "Resource not found", + 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..b09ded5 --- /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 = "Request finished successfully", useReturnTypeSchema = true) +public @interface OkResponse { +} diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml index 01e05b1..d5de074 100644 --- a/src/main/resources/application-dev.yml +++ b/src/main/resources/application-dev.yml @@ -20,4 +20,6 @@ spring: file: upload-dir: pdf +springdoc: + show-actuator: true From 3fdbf9fc477a7648bd9e647c76f0df625ed9288c Mon Sep 17 00:00:00 2001 From: MatheusVict Date: Mon, 4 Mar 2024 13:48:46 -0300 Subject: [PATCH 3/9] docs: files controller docs Signed-off-by: MatheusVict --- .../controllers/FilesStorageController.java | 16 +++++++++++++++- .../annotations/BadRequestResponse.java | 18 ++++++++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 src/main/java/com/institutosemprealerta/semprealerta/swagger/annotations/BadRequestResponse.java diff --git a/src/main/java/com/institutosemprealerta/semprealerta/application/controllers/FilesStorageController.java b/src/main/java/com/institutosemprealerta/semprealerta/application/controllers/FilesStorageController.java index 0d90555..64d166e 100644 --- a/src/main/java/com/institutosemprealerta/semprealerta/application/controllers/FilesStorageController.java +++ b/src/main/java/com/institutosemprealerta/semprealerta/application/controllers/FilesStorageController.java @@ -2,6 +2,10 @@ 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; @@ -15,6 +19,7 @@ import org.springframework.web.servlet.support.ServletUriComponentsBuilder; import java.io.IOException; +import java.net.URI; import java.util.List; @Controller @@ -29,6 +34,8 @@ public FilesStorageController(StorageService storageService) { @Operation(summary = "Upload a file", description = "Upload a file to the server") @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); @@ -38,12 +45,16 @@ public ResponseEntity uploadFile(@RequestPart("file") MultipartFile file .path(fileName) .toUriString(); - return ResponseEntity.ok("File uploaded successfully, file name: " + fileName + " on path: " + fileDownloadUri); + 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 a file", description = "Download a file from the server") + @OkResponse + @NotFoundResponse + @BadRequestResponse public ResponseEntity downloadFile( @PathVariable String fileName, HttpServletRequest request @@ -67,6 +78,9 @@ public ResponseEntity downloadFile( } @GetMapping("/list") + @Operation(summary = "List all files", description = "List all files from the server") + @OkResponse + @BadRequestResponse public ResponseEntity> listFiles() throws IOException { List fileNames = storageService.loadAll(); 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..7f03831 --- /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 = "Error on client side", + content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionPattern.class))) +public @interface BadRequestResponse { +} From ebb1de33759e8a2810a6f4ba8d89401a7439cb2e Mon Sep 17 00:00:00 2001 From: MatheusVict Date: Mon, 4 Mar 2024 14:02:02 -0300 Subject: [PATCH 4/9] docs: post controller docs Signed-off-by: MatheusVict --- .../controllers/PostController.java | 19 +++++++++++++++++++ .../semprealerta/domain/model/Post.java | 17 ++++++++++++++--- 2 files changed, 33 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/institutosemprealerta/semprealerta/application/controllers/PostController.java b/src/main/java/com/institutosemprealerta/semprealerta/application/controllers/PostController.java index 4ea45b0..7be3df5 100644 --- a/src/main/java/com/institutosemprealerta/semprealerta/application/controllers/PostController.java +++ b/src/main/java/com/institutosemprealerta/semprealerta/application/controllers/PostController.java @@ -2,6 +2,9 @@ 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; @@ -12,6 +15,7 @@ @RestController @RequestMapping("api/v1/posts") +@Tag(name = "Post", description = "Post management") public class PostController { private final PostService postService; @@ -20,28 +24,43 @@ public PostController(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/domain/model/Post.java b/src/main/java/com/institutosemprealerta/semprealerta/domain/model/Post.java index f09f901..7ed0db5 100644 --- a/src/main/java/com/institutosemprealerta/semprealerta/domain/model/Post.java +++ b/src/main/java/com/institutosemprealerta/semprealerta/domain/model/Post.java @@ -1,5 +1,7 @@ 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; @@ -10,15 +12,24 @@ @Setter public class Post { + @Hidden private Long id; - @NotBlank(message = "Title is mandatory") + + @NotBlank(message = "Title é obrigatorio") + @Schema(description = "Title do post", example = "Titulo do post") private String title; + private String slug; - @NotBlank(message = "Content is mandatory") + @NotBlank(message = "Content é obrigatorio") + @Schema(description = "Contenteudo do post", example = "Conteudo do post") private String content; - @NotBlank(message = "Banner is mandatory") + + @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) { From ddd2272e8de61d15be05341fd11f6ea8b21d2785 Mon Sep 17 00:00:00 2001 From: MatheusVict Date: Mon, 4 Mar 2024 14:04:49 -0300 Subject: [PATCH 5/9] docs: translate docs Signed-off-by: MatheusVict --- .../semprealerta/swagger/annotations/BadRequestResponse.java | 2 +- .../semprealerta/swagger/annotations/ConflictResponse.java | 2 +- .../semprealerta/swagger/annotations/CreatedResponse.java | 2 +- .../semprealerta/swagger/annotations/NoContentResponse.java | 2 +- .../semprealerta/swagger/annotations/NotFoundResponse.java | 2 +- .../semprealerta/swagger/annotations/OkResponse.java | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/institutosemprealerta/semprealerta/swagger/annotations/BadRequestResponse.java b/src/main/java/com/institutosemprealerta/semprealerta/swagger/annotations/BadRequestResponse.java index 7f03831..0ebeb1f 100644 --- a/src/main/java/com/institutosemprealerta/semprealerta/swagger/annotations/BadRequestResponse.java +++ b/src/main/java/com/institutosemprealerta/semprealerta/swagger/annotations/BadRequestResponse.java @@ -12,7 +12,7 @@ @Target({ElementType.METHOD, ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) -@ApiResponse(responseCode = "400", description = "Error on client side", +@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 index 80d47d5..0dbe12c 100644 --- a/src/main/java/com/institutosemprealerta/semprealerta/swagger/annotations/ConflictResponse.java +++ b/src/main/java/com/institutosemprealerta/semprealerta/swagger/annotations/ConflictResponse.java @@ -12,7 +12,7 @@ @Target({ElementType.METHOD, ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) -@ApiResponse(responseCode = "409", description = "There are some conflicts", +@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 index 1a72b8f..8ce4829 100644 --- a/src/main/java/com/institutosemprealerta/semprealerta/swagger/annotations/CreatedResponse.java +++ b/src/main/java/com/institutosemprealerta/semprealerta/swagger/annotations/CreatedResponse.java @@ -9,6 +9,6 @@ @Target({ElementType.METHOD, ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) -@ApiResponse(responseCode = "201", description = "Created Successfully", useReturnTypeSchema = true) +@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 index 77d52e5..8016606 100644 --- a/src/main/java/com/institutosemprealerta/semprealerta/swagger/annotations/NoContentResponse.java +++ b/src/main/java/com/institutosemprealerta/semprealerta/swagger/annotations/NoContentResponse.java @@ -9,6 +9,6 @@ @Target({ElementType.METHOD, ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) -@ApiResponse(responseCode = "204", description = "Request finished successfully without content", useReturnTypeSchema = true) +@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 index 6418927..9eb6e93 100644 --- a/src/main/java/com/institutosemprealerta/semprealerta/swagger/annotations/NotFoundResponse.java +++ b/src/main/java/com/institutosemprealerta/semprealerta/swagger/annotations/NotFoundResponse.java @@ -12,7 +12,7 @@ @Target({ElementType.METHOD, ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) -@ApiResponse(responseCode = "404", description = "Resource not found", +@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 index b09ded5..cf40ec7 100644 --- a/src/main/java/com/institutosemprealerta/semprealerta/swagger/annotations/OkResponse.java +++ b/src/main/java/com/institutosemprealerta/semprealerta/swagger/annotations/OkResponse.java @@ -10,6 +10,6 @@ @Target({ElementType.METHOD, ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) -@ApiResponse(responseCode = "200", description = "Request finished successfully", useReturnTypeSchema = true) +@ApiResponse(responseCode = "200", description = "Requisição finalizada com sucesso", useReturnTypeSchema = true) public @interface OkResponse { } From f5ef083f7e4ce3746bb9cfa3eb693b4bbd03730b Mon Sep 17 00:00:00 2001 From: MatheusVict Date: Mon, 4 Mar 2024 14:07:46 -0300 Subject: [PATCH 6/9] docs: translate files controller docs Signed-off-by: MatheusVict --- .../application/controllers/FilesStorageController.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/institutosemprealerta/semprealerta/application/controllers/FilesStorageController.java b/src/main/java/com/institutosemprealerta/semprealerta/application/controllers/FilesStorageController.java index 64d166e..8dffd37 100644 --- a/src/main/java/com/institutosemprealerta/semprealerta/application/controllers/FilesStorageController.java +++ b/src/main/java/com/institutosemprealerta/semprealerta/application/controllers/FilesStorageController.java @@ -32,7 +32,7 @@ public FilesStorageController(StorageService storageService) { this.storageService = storageService; } - @Operation(summary = "Upload a file", description = "Upload a file to the server") + @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 @@ -51,7 +51,7 @@ public ResponseEntity uploadFile(@RequestPart("file") MultipartFile file @GetMapping("/download/{fileName:.+}") @ResponseBody - @Operation(summary = "Download a file", description = "Download a file from the server") + @Operation(summary = "Download de um arquivo", description = "Baixe um arquivo pelo nome do arquivo") @OkResponse @NotFoundResponse @BadRequestResponse @@ -78,7 +78,7 @@ public ResponseEntity downloadFile( } @GetMapping("/list") - @Operation(summary = "List all files", description = "List all files from the server") + @Operation(summary = "List todos os arquivos", description = "Liste todos os arquivos do servidor") @OkResponse @BadRequestResponse public ResponseEntity> listFiles() throws IOException { From 616a5ccf7e0ba421b80f465f92ff790d1b0c4554 Mon Sep 17 00:00:00 2001 From: MatheusVict Date: Mon, 4 Mar 2024 14:12:22 -0300 Subject: [PATCH 7/9] docs: user controller docs Signed-off-by: MatheusVict --- .../controllers/UserController.java | 22 ++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/institutosemprealerta/semprealerta/application/controllers/UserController.java b/src/main/java/com/institutosemprealerta/semprealerta/application/controllers/UserController.java index 5866eba..a98fa57 100644 --- a/src/main/java/com/institutosemprealerta/semprealerta/application/controllers/UserController.java +++ b/src/main/java/com/institutosemprealerta/semprealerta/application/controllers/UserController.java @@ -4,6 +4,9 @@ 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; @@ -11,6 +14,7 @@ @RestController @RequestMapping("api/v1/user") +@Tag(name = "User", description = "Administração de usuários") public class UserController { private final UserService userService; @@ -20,30 +24,46 @@ public UserController(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.status(HttpStatus.NO_CONTENT).build(); + 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(); From b7709ee3df6311bce866dd626b91619c799b645f Mon Sep 17 00:00:00 2001 From: MatheusVict Date: Mon, 4 Mar 2024 14:20:22 -0300 Subject: [PATCH 8/9] chore: docs infos and authorization Signed-off-by: MatheusVict --- .../config/ApplicationConfig.java | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/src/main/java/com/institutosemprealerta/semprealerta/infrastructure/config/ApplicationConfig.java b/src/main/java/com/institutosemprealerta/semprealerta/infrastructure/config/ApplicationConfig.java index f144020..b7adbce 100644 --- a/src/main/java/com/institutosemprealerta/semprealerta/infrastructure/config/ApplicationConfig.java +++ b/src/main/java/com/institutosemprealerta/semprealerta/infrastructure/config/ApplicationConfig.java @@ -2,12 +2,22 @@ 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 { @@ -20,4 +30,29 @@ public SlugGenerator slugGenerator() { 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/"))); + } } From 21e8d361132aee2f77f538b674a209e494bd7e31 Mon Sep 17 00:00:00 2001 From: MatheusVict Date: Mon, 4 Mar 2024 14:23:39 -0300 Subject: [PATCH 9/9] docs: user dto Signed-off-by: MatheusVict --- .../semprealerta/domain/model/UserDTO.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/main/java/com/institutosemprealerta/semprealerta/domain/model/UserDTO.java b/src/main/java/com/institutosemprealerta/semprealerta/domain/model/UserDTO.java index bb70fb5..004a824 100644 --- a/src/main/java/com/institutosemprealerta/semprealerta/domain/model/UserDTO.java +++ b/src/main/java/com/institutosemprealerta/semprealerta/domain/model/UserDTO.java @@ -7,6 +7,7 @@ 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; @@ -14,21 +15,32 @@ 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 ) {