Commit 6c7dae98 authored by Arthur Kunzler's avatar Arthur Kunzler
Browse files

Merge develop into 'feature/send-to-blockchain'

parents ac4bc0bd 088d9841
Showing with 253 additions and 48 deletions
+253 -48
package com.ages.blockchainapi;
import com.ages.blockchainapi.certificates.CertificateEntity;
import com.ages.blockchainapi.certificates.CertificateService;
import com.ages.blockchainapi.companies.CompanyEntity;
import com.ages.blockchainapi.companies.CompanyService;
import com.ages.blockchainapi.owners.OwnerEntity;
import com.ages.blockchainapi.owners.OwnerService;
import com.ages.blockchainapi.permissions.IPermissionRepository;
import com.ages.blockchainapi.permissions.PermissionEntity;
import com.ages.blockchainapi.permissions.PermissionService;
......@@ -14,6 +18,7 @@ import org.springframework.boot.CommandLineRunner;
import org.springframework.context.annotation.Profile;
import org.springframework.stereotype.Component;
import java.time.LocalDate;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
......@@ -26,12 +31,16 @@ public class CommandLineAppStartupRunner implements CommandLineRunner {
private final CompanyService companyService;
private final PermissionService permissionService;
private final UserService userService;
private final CertificateService certificateService;
private final OwnerService ownerService;
private final IPermissionRepository permissionRepository;
public CommandLineAppStartupRunner(CompanyService companyService, PermissionService permissionService, UserService userService, IPermissionRepository permissionRepository) {
public CommandLineAppStartupRunner(CompanyService companyService, PermissionService permissionService, UserService userService, CertificateService certficateService, OwnerService ownerService, IPermissionRepository permissionRepository) {
this.companyService = companyService;
this.permissionService = permissionService;
this.userService = userService;
this.certificateService = certficateService;
this.ownerService = ownerService;
this.permissionRepository = permissionRepository;
}
......@@ -67,6 +76,12 @@ public class CommandLineAppStartupRunner implements CommandLineRunner {
company1);
userService.save(user4);
OwnerEntity owner1 = buildOwner("abc@abc.com", "12345678910");
ownerService.save(owner1);
CertificateEntity certificate1 = buildCertificate("Certificado 1", LocalDate.now(), "Curso 1", "123456", "https://www.google.com", true, owner1, user1);
certificateService.save(certificate1);
log.info("Terminou de popular");
}
......@@ -96,6 +111,26 @@ public class CommandLineAppStartupRunner implements CommandLineRunner {
.build();
}
private CertificateEntity buildCertificate(String name, LocalDate courseConclusionDate, String course, String certificateNumber, String documentUrl, boolean active, OwnerEntity owner, UserEntity createdBy) {
return CertificateEntity.builder()
.name(name)
.courseConclusionDate(courseConclusionDate)
.course(course)
.certificateNumber(certificateNumber)
.documentUrl(documentUrl)
.active(active)
.owner(owner)
.createdBy(createdBy)
.build();
}
private OwnerEntity buildOwner(String email, String rg) {
return OwnerEntity.builder()
.email(email)
.rg(rg)
.build();
}
private Set<PermissionEntity> getAllPermissions(){
List<PermissionEntity> allPermissions = this.permissionRepository.findAll();
return allPermissions.stream()
......
......@@ -139,8 +139,6 @@ public class BlockchainService {
private BlockchainReturnReceipt buildTransactionReceipt(TransactionReceipt receipt) {
BigInteger blockchaintoken = new BigInteger(removeOx(receipt.getLogs().getFirst().getTopics().getLast()), 16);
System.out.println(receipt.getLogs().getFirst().getTopics().getLast());
System.out.println(blockchaintoken);
return BlockchainReturnReceipt.builder()
.to(receipt.getTo())
......
......@@ -8,7 +8,13 @@ import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/certificates")
......@@ -30,5 +36,15 @@ public class CertificateController {
return ResponseEntity.status(HttpStatus.CREATED).body(certificate);
}
@Operation(summary = "Buscar certificado por ID", description = "Retorna um certificado")
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "Operação bem sucedida."),
@ApiResponse(responseCode = "404", description = "Certificado não encontrado")
})
@GetMapping("/{certificateId}")
public ResponseEntity<CertificateSearchDTO> getCertificateById(@PathVariable("certificateId") Long certificateId) {
var company = this.certService.findById(certificateId);
return ResponseEntity.ok(CertificateSearchDTO.fromEntity(company));
}
}
package com.ages.blockchainapi.certificates;
import java.time.LocalDate;
import org.springframework.format.annotation.DateTimeFormat;
import com.ages.blockchainapi.users.UserCertificateDTO;
import com.ages.blockchainapi.owners.OwnerEntity;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.google.firebase.internal.NonNull;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@JsonInclude(JsonInclude.Include.NON_NULL)
public class CertificateSearchDTO {
@NonNull
private Long id;
@NonNull
private String name;
@DateTimeFormat(pattern = "yyyy-MM-dd")
private LocalDate courseConclusionDate;
@NonNull
private String course;
@NonNull
private String certificateNumber;
@NonNull
private String documentUrl;
@NonNull
private boolean active;
@NonNull
private OwnerEntity owner;
@NonNull
private UserCertificateDTO createdBy;
public static CertificateSearchDTO fromEntity(CertificateEntity entity){
return CertificateSearchDTO.builder()
.id(entity.getId())
.name(entity.getName())
.courseConclusionDate(entity.getCourseConclusionDate())
.course(entity.getCourse())
.certificateNumber(entity.getCertificateNumber())
.documentUrl(entity.getDocumentUrl())
.active(entity.getActive())
.owner(entity.getOwner())
.createdBy(UserCertificateDTO.fromEntity(entity.getCreatedBy()))
.build();
}
}
......@@ -2,9 +2,11 @@ package com.ages.blockchainapi.certificates;
import com.ages.blockchainapi.companies.CompanyService;
import com.ages.blockchainapi.exception.ETHCertificateCreationFailed;
import com.ages.blockchainapi.exception.NotFoundException;
import com.ages.blockchainapi.owners.OwnerEntity;
import com.ages.blockchainapi.owners.OwnerService;
import com.ages.blockchainapi.users.UserDetailsDTO;
import com.ages.blockchainapi.users.UserEntity;
import com.ages.blockchainapi.users.UserService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
......@@ -19,15 +21,15 @@ public class CertificateService {
private final OwnerService ownerService;
private final BlockchainService blockchainService;
private final UserService userService;
private final CompanyService companyService;
public CertificateEntity create(CertificateCreationDTO certDTO,String token){
OwnerEntity owner = this.ownerService.createOrGetExisting(certDTO.getOwnerInfo());
String UUID = generateCertificateUuid();
UserDetailsDTO user = userService.getUserDetails(token);
UserEntity user = userService.getUserDetails(token);
ETHCertificateDTO ethCertificate = buildETHCertificate(certDTO, UUID, user.getCompanyId());
ETHCertificateDTO ethCertificate = buildETHCertificate(certDTO, UUID, user.getCompany().getId());
BlockchainReturnReceipt blockchainReceipt = this.blockchainService.mintNFT(ethCertificate);
if (blockchainReceipt.getStatus().equals("0x01")){
......@@ -42,13 +44,22 @@ public class CertificateService {
.courseConclusionDate(certDTO.getCourseConclusionDate())
.uuid(UUID)
.blockchainToken(blockchainReceipt.getTokenID())
.issuerCompany(companyService.findById(user.getCompanyId()))
.issuerCompany(user.getCompany())
.createdBy(userService.findByEmail(user.getEmail()))
.build();
return this.certRepository.save(certificate);
}
public CertificateEntity save(CertificateEntity certificate){
return this.certRepository.save(certificate);
}
public CertificateEntity findById(Long certificateId) {
return this.certRepository.findById(certificateId)
.orElseThrow(() -> new NotFoundException("Certificado não encontrado"));
}
private ETHCertificateDTO buildETHCertificate(CertificateCreationDTO certCreationDTO, String uuid, Long companyid){
return ETHCertificateDTO.builder()
.email(certCreationDTO.getOwnerInfo().getEmail())
......@@ -60,11 +71,8 @@ public class CertificateService {
.university(BigInteger.valueOf(companyid))
.build();
}
private String generateCertificateUuid(){
// TODO: implementar logica que vai gerar um token id unico para o certificado
String aux = UUID.randomUUID().toString();
System.out.println(aux);
return aux;
private String generateCertificateUuid(){
return UUID.randomUUID().toString();
}
}
\ No newline at end of file
}
......@@ -35,4 +35,8 @@ public class OwnerService {
}
return ownerExists;
}
public OwnerEntity save(OwnerEntity owner){
return this.ownerRepository.save(owner);
}
}
package com.ages.blockchainapi.users;
import com.ages.blockchainapi.companies.CompanyEntity;
import org.antlr.v4.runtime.atn.SemanticContext.AND;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.CrudRepository;
import org.springframework.data.repository.query.Param;
......@@ -12,9 +16,20 @@ import java.util.Optional;
public interface IUserRepository extends CrudRepository<UserEntity, Long> {
List<UserEntity> findAll();
@Query("SELECT CASE WHEN COUNT(u) > 0 THEN true ELSE false END FROM UserEntity u WHERE u.email = :email")
boolean existsByEmail(@Param("email") String email);
@Query("""
SELECT u FROM UserEntity u WHERE u.company = :company
AND (:name IS NULL OR u.name LIKE %:name%)
""")
Page<UserEntity> findByCompany(
@Param("name") String name,
@Param("company") CompanyEntity company,
Pageable pageable);
Optional<UserEntity> findByEmail(String email);
}
package com.ages.blockchainapi.users;
import com.fasterxml.jackson.annotation.JsonInclude;
import jakarta.validation.constraints.Email;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@JsonInclude(JsonInclude.Include.NON_NULL)
public class UserCertificateDTO {
@NotNull
private Long id;
@NotNull(message = "é necessário informar um e-mail")
@Email(message = "e-mail inválido")
private String email;
@NotBlank(message = "nome deve conter pelo menos um caractere não vazio")
private String name;
@NotNull
private boolean active;
public static UserCertificateDTO fromEntity(UserEntity entity){
return UserCertificateDTO.builder()
.id(entity.getId())
.email(entity.getEmail())
.name(entity.getName())
.active(entity.getActive())
.build();
}
}
......@@ -6,10 +6,13 @@ import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.springframework.data.web.PageableDefault;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.data.domain.Sort;
import java.util.List;
@RequiredArgsConstructor
......@@ -19,14 +22,18 @@ import java.util.List;
public class UserController {
private final UserService userService;
@GetMapping
@Operation(summary = "Listar todos usuários")
@GetMapping()
@Operation(summary = "Listar usuários de uma empresa")
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "Operação sucedida"),
@ApiResponse(responseCode = "404", description = "Não encontrado")
@ApiResponse(responseCode = "400", description = "Parâmetros inválidos")
})
public List<UserEntity> getAll(){
return this.userService.findAll();
public Page<UserEntity> findByCompany(
@RequestParam(required = true) String name,
@PageableDefault(sort = "id", direction = Sort.Direction.DESC) Pageable pageable,
@RequestHeader(value = "Authorization") String token
){
return this.userService.findByCompany(name, pageable, token);
}
@PostMapping()
......@@ -37,9 +44,9 @@ public class UserController {
@ApiResponse(responseCode = "404", description = "Entidade não encontrada"),
@ApiResponse(responseCode = "409", description = "Entidade já existente")
})
public ResponseEntity<UserEntity> employeeRegistration(@Valid @RequestBody UserDTO userDTO) {
this.userService.validate(userDTO);
UserEntity user = this.userService.create(userDTO);
public ResponseEntity<UserEntity> create(@Valid @RequestBody UserDTO userDTO,
@RequestHeader(value = "Authorization") String currentUserToken) {
UserEntity user = this.userService.create(userDTO, currentUserToken);
return ResponseEntity.status(HttpStatus.CREATED).body(user);
}
......@@ -50,6 +57,7 @@ public class UserController {
@ApiResponse(responseCode = "401", description = "Token de autenticação inválido")
})
public UserDetailsDTO getUserDetails(@RequestHeader(value = "Authorization") String token) {
return this.userService.getUserDetails(token);
var userDetails = this.userService.getUserDetails(token);
return UserDetailsDTO.fromDomain(userDetails);
}
}
......@@ -7,12 +7,11 @@ import com.ages.blockchainapi.exception.NotFoundException;
import com.ages.blockchainapi.permissions.PermissionEntity;
import com.ages.blockchainapi.permissions.PermissionService;
import com.ages.blockchainapi.utils.enums.PermissionsEnum;
import jakarta.persistence.EntityNotFoundException;
import lombok.RequiredArgsConstructor;
import org.springframework.security.core.userdetails.User;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import java.util.HashSet;
import java.util.List;
import java.util.Optional;
import java.util.Set;
......@@ -27,44 +26,57 @@ public class UserService {
private final CompanyService companyService;
private final PermissionService permissionService;
public List<UserEntity> findAll(){
return this.userRepository.findAll();
}
public UserEntity create(UserDTO userDTO, String currentUserToken) {
if (this.userRepository.existsByEmail(userDTO.getEmail())) {
throw new AlreadyExistsException("Usuario com este email já existente");
}
validatePermissions(userDTO.getPermissions(), getUserDetails(currentUserToken).getPermissions());
public UserEntity create(UserDTO userDTO) {
if (this.userRepository.existsByEmail(userDTO.getEmail())) throw new AlreadyExistsException("Usuario com este email já existente");
firebaseService.createFirebaseUser(userDTO);
UserEntity userEntity = UserEntity.builder()
.name(userDTO.getName())
.email(userDTO.getEmail())
.active(true)
.permissions(this.permissionService.convertPermissions(userDTO.getPermissions()))
.company(companyService.findById(userDTO.getCompanyId()))
.build();
.name(userDTO.getName())
.email(userDTO.getEmail())
.active(true)
.permissions(this.permissionService.convertPermissions(userDTO.getPermissions()))
.company(companyService.findById(userDTO.getCompanyId()))
.build();
return this.userRepository.save(userEntity);
}
public void validate(UserDTO userDTO){
if (this.userRepository.existsByEmail(userDTO.getEmail())) {
throw new AlreadyExistsException("Usuário com o mesmo email já cadastrado.");
}
public UserEntity save(UserEntity user) {
return this.userRepository.save(user);
}
public UserEntity save(UserEntity user){
return this.userRepository.save(user);
public UserEntity getUserDetails(String token) {
String userEmail = firebaseService.getUserEmailFromToken(token);
return userRepository.findByEmail(userEmail)
.orElseThrow(() -> new NotFoundException("Usuário não encontrado"));
}
public UserDetailsDTO getUserDetails(String token) {
public Page<UserEntity> findByCompany(String nameFilter, Pageable pageable, String token) {
String userEmail = firebaseService.getUserEmailFromToken(token);
Optional<UserEntity> user = userRepository.findByEmail(userEmail);
if (user.isEmpty()){
throw new NotFoundException("Usuário do Firebase inexistente no banco da aplicação.");
}
return UserDetailsDTO.fromDomain(user.get());
return this.userRepository.findByCompany(nameFilter, user.get().getCompany(), pageable);
}
public UserEntity findByEmail(String email){
return this.userRepository.findByEmail(email).orElseThrow(() -> new NotFoundException("Empresa não encontrada.") );
return this.userRepository.findByEmail(email)
.orElseThrow(() -> new NotFoundException("Empresa não encontrada.") );
}
private void validatePermissions(List<String> permissionsToCreate, Set<PermissionEntity> ownedPermissions) {
var ownedPermissionsSet = ownedPermissions.stream()
.map(PermissionEntity::getKey)
.collect(Collectors.toSet());
var permissionsToCreateSet = permissionsToCreate.stream()
.map(PermissionsEnum::valueOf)
.collect(Collectors.toSet());
if (!ownedPermissionsSet.containsAll(permissionsToCreateSet)) {
throw new NotFoundException("Permissões inválidas");
}
}
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment