Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Developer #7

Merged
merged 70 commits into from
Mar 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
70 commits
Select commit Hold shift + click to select a range
9eb54aa
feat: add user entity
MatheusVict Feb 20, 2024
f5fbef3
feat: add migrations
MatheusVict Feb 20, 2024
4982e86
repository
MatheusVict Feb 20, 2024
63e36c2
feat: add repository hexagonal
MatheusVict Feb 20, 2024
652112f
feat: add find by email and registration
MatheusVict Feb 20, 2024
a1cce5b
feat: add user service
MatheusVict Feb 20, 2024
02bd841
refactor: user directory
MatheusVict Feb 20, 2024
d205387
refactor: user repository to use adapter
MatheusVict Feb 20, 2024
673d8d6
feat: user service
MatheusVict Feb 20, 2024
e6cb55f
feat: controller
MatheusVict Feb 20, 2024
996b705
feat: find by registration
MatheusVict Feb 20, 2024
c6447ee
fix: update user by id dupicitly
MatheusVict Feb 20, 2024
47cf7dd
feat: add unique registration
MatheusVict Feb 20, 2024
ea36a40
feat: validation dto
MatheusVict Feb 21, 2024
da85960
Merge pull request #1 from Hangar-Tech/feat-users
MatheusVict Feb 21, 2024
1df51be
feat: add upload, download and list all files
MatheusVict Feb 26, 2024
2ee0aad
chore: change entity properties
MatheusVict Feb 26, 2024
b36ca65
feat: save file information at the database
MatheusVict Feb 26, 2024
90bdb84
feat: add file repository
MatheusVict Feb 26, 2024
883754f
feat: add file controller
MatheusVict Feb 26, 2024
1989440
tests: jpa user repository test
MatheusVict Feb 27, 2024
77ad104
tests: user service test
MatheusVict Feb 27, 2024
ccb1368
test: jpa adapter repository
MatheusVict Feb 27, 2024
532d7c5
tests: user controller
MatheusVict Feb 27, 2024
467a02a
tests: jpa file repository test
MatheusVict Feb 28, 2024
0550cfd
test: jpa file repository adapter
MatheusVict Feb 28, 2024
df3f7bd
test: service test
MatheusVict Feb 29, 2024
1105bdb
test: files tests
MatheusVict Feb 29, 2024
e6c4da9
feat: post entity
MatheusVict Mar 1, 2024
2c3e25a
feat: add slugify generator
MatheusVict Mar 1, 2024
d925272
refactor: adjusct entity
MatheusVict Mar 2, 2024
22eff4f
feat: post repository
MatheusVict Mar 2, 2024
5049dfb
chore: change flyway cache
MatheusVict Mar 2, 2024
cfcf388
chore: page size
MatheusVict Mar 2, 2024
440b007
fix: return page
MatheusVict Mar 2, 2024
ee29a8e
fix: transform on bean
MatheusVict Mar 2, 2024
f604c6d
fix: entity properties
MatheusVict Mar 2, 2024
0360501
feat: rest post controller
MatheusVict Mar 2, 2024
585de19
test: jpa post repository
MatheusVict Mar 2, 2024
5a8fdf3
test: jpa post repository adapter
MatheusVict Mar 2, 2024
cb9f537
test: post service test
MatheusVict Mar 2, 2024
e2c00d4
test: controller tests
MatheusVict Mar 2, 2024
5de075f
Merge pull request #4 from Hangar-Tech/feat-posts
MatheusVict Mar 4, 2024
63333e0
fix: container image tags
MatheusVict Mar 4, 2024
210a45f
feat: user exceptions
MatheusVict Mar 4, 2024
b2e5618
feat: files and posts exceptions
MatheusVict Mar 4, 2024
f3f43ff
feat: dto valid
MatheusVict Mar 4, 2024
430ece7
feat: global exception handler
MatheusVict Mar 4, 2024
248dee5
feat: generate new slug
MatheusVict Mar 4, 2024
3b198b7
Merge pull request #5 from Hangar-Tech/feat-excetpion-handler
MatheusVict Mar 4, 2024
ba2d941
feat: add swagger plugin
MatheusVict Mar 4, 2024
65ee5c9
feat: swagger custom response annotations
MatheusVict Mar 4, 2024
3fdbf9f
docs: files controller docs
MatheusVict Mar 4, 2024
ebb1de3
docs: post controller docs
MatheusVict Mar 4, 2024
ddd2272
docs: translate docs
MatheusVict Mar 4, 2024
f5ef083
docs: translate files controller docs
MatheusVict Mar 4, 2024
616a5cc
docs: user controller docs
MatheusVict Mar 4, 2024
b7709ee
chore: docs infos and authorization
MatheusVict Mar 4, 2024
21e8d36
docs: user dto
MatheusVict Mar 4, 2024
4d4c9c9
Merge pull request #6 from Hangar-Tech/feat-add-swagger
MatheusVict Mar 4, 2024
d04b24f
fix: fix test asserts
MatheusVict Mar 4, 2024
2a94409
feat: add spring security
MatheusVict Mar 5, 2024
f90dcbc
generate token and protect routes
MatheusVict Mar 5, 2024
c46d534
feat: verify token
MatheusVict Mar 6, 2024
52026ed
test: auth controller test
MatheusVict Mar 6, 2024
16ef437
test: global handler exception test
MatheusVict Mar 6, 2024
18c87ae
test: slugify test
MatheusVict Mar 6, 2024
f5edcdc
test: authorization service test
MatheusVict Mar 6, 2024
f554e17
test: authentication service test
MatheusVict Mar 6, 2024
57b6597
Merge pull request #8 from Hangar-Tech/feat-authentication
MatheusVict Mar 6, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
HELP.md
pdf/
target/
!.mvn/wrapper/maven-wrapper.jar
!**/src/main/**/target/
!**/src/test/**/target/
htmlReport

### STS ###
.apt_generated
Expand Down
8 changes: 4 additions & 4 deletions mvnw.cmd
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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
Expand Down
47 changes: 46 additions & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
<description>sempre-alerta</description>
<properties>
<java.version>17</java.version>
<springdoc-openapi-starter-webmvc-ui.version>2.3.0</springdoc-openapi-starter-webmvc-ui.version>
</properties>
<dependencies>
<dependency>
Expand All @@ -37,11 +38,34 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
<version>${springdoc-openapi-starter-webmvc-ui.version}</version>
</dependency>
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-starter-webmvc-api</artifactId>
<version>${springdoc-openapi-starter-webmvc-ui.version}</version>
</dependency>
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-core</artifactId>
</dependency>

<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
Expand All @@ -52,6 +76,23 @@
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!-- https://mvnrepository.com/artifact/com.github.slugify/slugify -->
<dependency>
<groupId>com.github.slugify</groupId>
<artifactId>slugify</artifactId>
<version>3.0.6</version>
</dependency>
<dependency>
<groupId>com.github.javafaker</groupId>
<artifactId>javafaker</artifactId>
<version>1.0.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>4.4.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
Expand Down Expand Up @@ -93,6 +134,10 @@
<artifactId>lombok</artifactId>
</exclude>
</excludes>
<image>
<name>matheusvict/${project.artifactId}:${project.version}</name>
</image>
<pullPolicy>IF_NOT_PRESENT</pullPolicy>
</configuration>
</plugin>
</plugins>
Expand Down
Original file line number Diff line number Diff line change
@@ -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) {
Expand Down
Original file line number Diff line number Diff line change
@@ -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);
}
}
Original file line number Diff line number Diff line change
@@ -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<String> 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<Resource> 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<List<FileResponse>> listFiles() throws IOException {
List<FileResponse> fileNames = storageService.loadAll();

return ResponseEntity.ok(fileNames);
}
}
Original file line number Diff line number Diff line change
@@ -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<Page<Post>> 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<Post> 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();
}
}
Original file line number Diff line number Diff line change
@@ -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<UserResponse> 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<UserResponse> 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();
}
}
Loading
Loading