Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package com.orderflow.ecommerce.controllers;

import com.orderflow.ecommerce.dtos.UserDto;
import com.orderflow.ecommerce.services.UserService;
import jakarta.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.support.ServletUriComponentsBuilder;

import java.net.URI;

@RestController
@RequestMapping("/users")
public class UserController {

@Autowired
private UserService service;

@GetMapping(value = "/{id}")
public ResponseEntity<UserDto> findById(@PathVariable Long id) {
return ResponseEntity.ok(service.findById(id));
}

@GetMapping
public ResponseEntity<Page<UserDto>> findAll(Pageable pageable) {
return ResponseEntity.ok().body(service.findAllPaged(pageable));
}

@GetMapping(params = "email")
public ResponseEntity<UserDto> findByEmail(@RequestParam String email) {
return ResponseEntity.ok().body(service.findByEmail(email));
}

@Valid

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • This annotation is unnecessary; what validates the body is the @Valid within the method parameters.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed.

@PostMapping
public ResponseEntity<UserDto> insert(@Valid @RequestBody UserDto dto) {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • Change the request from UserDto to UserRequest when creating this DTO, as per the note added to UserDto, so that the return should be ResponseEntity.

dto = service.insert(dto);
URI uri = ServletUriComponentsBuilder.fromCurrentRequest().path("/{id}")
.buildAndExpand(dto.id()).toUri();
return ResponseEntity.created(uri).body(dto);
}

@DeleteMapping(value = "/{id}")
public ResponseEntity<Void> delete(@PathVariable Long id, @RequestParam(required = false) boolean verify) {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • Remove boolean verify as explained in the note placed in the service.

service.delete(id, verify);
return ResponseEntity.noContent().build();
}

@PutMapping(value = "/{id}")
public ResponseEntity<UserDto> update(@PathVariable Long id, @Valid @RequestBody UserDto dto) {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • Change the request from UserDto to UserRequest when creating this DTO, as per the note added to UserDto, so that the return should be ResponseEntity.

return ResponseEntity.ok().body(service.update(id, dto));
}
}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • Remove the entire ControllerExceptionHandler, as exception handling is already present in the GlobalExceptionHandler of the project. Therefore, you should add the handlers and exceptions to the GlobalExceptionHandler.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ControllerExceptionHandler removed, Handlers moved to GlobalExceptionHandler.

Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package com.orderflow.ecommerce.controllers.exceptions;

import com.orderflow.ecommerce.dtos.ErrorResponse;
import com.orderflow.ecommerce.exceptions.DuplicateResourceValidationException;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.dao.DataIntegrityViolationException;
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.Instant;

@ControllerAdvice
public class ControllerExceptionHandler {

@ExceptionHandler(MethodArgumentNotValidException.class)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • The handler for MethodArgumentNotValidException is duplicated; you should evaluate the other developer's implementation to see if it's feasible for your needs, and if necessary, make changes in a way that satisfies both your implementation and the other developer's.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Refactored MethodArgumentNotValidException handler in GlobalExceptionHandler to replace this.

public ResponseEntity<ValidationError> validation(MethodArgumentNotValidException ex, HttpServletRequest request) {
HttpStatus status = HttpStatus.UNPROCESSABLE_ENTITY;
ValidationError err = new ValidationError();
err.setTimestamp(Instant.now());
err.setStatus(status.value());
err.setError("Validation exception");
err.setMessage(ex.getMessage());
err.setPath(request.getRequestURI());

for (FieldError f : ex.getBindingResult().getFieldErrors()) {
err.addError(f.getField(), f.getDefaultMessage());
}

return ResponseEntity.status(status).body(err);
}
@ExceptionHandler(DataIntegrityViolationException.class)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • Implement in GlobalExceptionHandler.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

public ResponseEntity<ErrorResponse> handleIntegrityViolation(DataIntegrityViolationException ex, HttpServletRequest request) {
HttpStatus status = HttpStatus.BAD_REQUEST;
ErrorResponse err = new ErrorResponse(Instant.now(), status.value(), ex.getMessage(), request.getRequestURI());
return ResponseEntity.status(status).body(err);
}

@ExceptionHandler(DuplicateResourceValidationException.class)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • Implement in GlobalExceptionHandler.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

public ResponseEntity<ValidationError> handleDuplicateResource(DuplicateResourceValidationException ex, HttpServletRequest request) {
HttpStatus status = HttpStatus.UNPROCESSABLE_ENTITY;
ValidationError err = new ValidationError();
err.setTimestamp(Instant.now());
err.setStatus(status.value());
err.setError("Validation exception");
err.setMessage(ex.getMessage());
err.setPath(request.getRequestURI());

ex.getErrors().forEach(f -> {
err.addError(f.getFieldName(), f.getMessage());
});

return ResponseEntity.status(status).body(err);
}
}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • Move the FieldMessage to api/src/main/java/com/orderflow/ecommerce/dtos/.
    The record is an HTTP response template and should remain with the DTOS.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FieldMessage moved to api/src/main/java/com/orderflow/ecommerce/dtos/

Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.orderflow.ecommerce.controllers.exceptions;

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class FieldMessage {
private String fieldName;
private String message;
}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • Remove this file, as we already have ErrorResponse in api/src/main/java/com/orderflow/ecommerce/dtos/ErrorResponse.java as a project standard.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed after refator ValidationError.

Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.orderflow.ecommerce.controllers.exceptions;

import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

import java.time.Instant;

@Getter
@Setter
@NoArgsConstructor
public class StandardError {
private Instant timestamp;
private Integer status;
private String error;
private String message;
private String path;

}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • Move it to api/src/main/java/com/orderflow/ecommerce/dtos, and extend ErrorResponse, so that it conforms to the project standard.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved to DTO. ErrorResponse can not be extended once it is a Record, but ValidationError refactored to use ErrorResponse instead of extend StandardError (removed).

Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.orderflow.ecommerce.controllers.exceptions;

import lombok.Getter;

import java.util.ArrayList;
import java.util.List;

@Getter
public class ValidationError extends StandardError{
private final List<FieldMessage> errors = new ArrayList<>();

public void addError(String fieldName, String message) {
errors.add(new FieldMessage(fieldName, message));
}
}
52 changes: 52 additions & 0 deletions api/src/main/java/com/orderflow/ecommerce/dtos/UserDto.java

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • Split the UserDTO into UserRequest and UserResponse, so that each has what is needed, without fields that don't make sense in the context, since a single DTO can generate several problems in the future.

Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package com.orderflow.ecommerce.dtos;

import com.orderflow.ecommerce.entities.User;
import jakarta.validation.constraints.Email;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Pattern;
import jakarta.validation.constraints.Size;

import java.time.LocalDate;

public record UserDto(
Long id,
@NotBlank(message = "Campo requerido")
String name,
@NotBlank(message = "Campo requerido")
@Email(message = "Email inválido")
String email,
@NotBlank(message = "Campo requerido")
@Pattern(
regexp = "^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)(?=.*[@$!%*?&.]).{8,}$",

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • Validate the regex implementation, because if you include the special characters # and _, the regex doesn't consider them as special characters. Check for a better implementation or add the special characters.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Coundn't find much referenced for whats should we consider as special caracteres (as we don't have this specified for the project), but the one or two articles I found consider @$!%*?&. I added . by my own.
Added # and _ to the regex.
Or should I create a @Password configuration instead?

message = "A senha deve conter pelo menos 8 caracteres, incluindo letras maiúsculas, minúsculas, números e caracteres especiais"
)
String password,
String taxId,
String stateRegistration,
String phone,
LocalDate birthDate,
Boolean taxpayer,
String googleId,
@Size(max = 40, message = "Máximo 40 caracteres")
String street,
@Size(max = 40, message = "Máximo 40 caracteres")
String complement,
@Size(max = 10, message = "Máximo 10 caracteres")
String number,
@Size(max = 40, message = "Máximo 40 caracteres")
String neighborhood,
@Size(max = 40, message = "Máximo 40 caracteres")
String city,
@Size(max = 40, message = "Máximo 40 caracteres")
String country,
@Size(max = 2, message = "Máximo 2 caracteres")
String state,
@Size(max = 10, message = "Máximo 10 caracteres")
String zipCode
) {
public UserDto(User entity) {
this(entity.getId(), entity.getName(), entity.getEmail(), entity.getPassword(), entity.getTaxId(), entity.getStateRegistration(), entity.getPhone(), entity.getBirthDate(), entity.getTaxpayer(), entity.getGoogleId(), entity.getStreet(), entity.getComplement(), entity.getNumber(), entity.getNeighborhood(), entity.getCity(), entity.getCountry(), entity.getState(), entity.getZipCode());
}
}


74 changes: 74 additions & 0 deletions api/src/main/java/com/orderflow/ecommerce/entities/User.java

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • Remove comments from the class to maintain a clean code project standard.

Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package com.orderflow.ecommerce.entities;

import jakarta.persistence.*;
import lombok.*;

import java.time.LocalDate;

@Entity
@Table(name = "tb_user")
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode(of = "id")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@Column(nullable = false)
private String name;
@Column(nullable = false, unique = true)
private String email;
private String password;


// Customer information for Invoices
/**
* CPF or CNPJ
*/
@Column(name = "tax_id", nullable = false, unique = true, length = 20)
private String taxId;

/**
* State registration (IE)
*/
@Column(length = 30)
private String stateRegistration;

private String phone;
private LocalDate birthDate;

/**
* Used in Invoices (NF-e)
*/
private Boolean taxpayer;

/**
* Google API
*/
@Column(unique = true)
private String googleId;

/**
* private Address address;
*/
@Column(length = 40)
private String street;
@Column(length = 40)
private String complement;
@Column(length = 10)
private String number;
@Column(length = 40)
private String neighborhood;
@Column(length = 40)
private String city;
@Column(length = 40)
private String country;
@Column(length = 2)
private String state;
@Column(length = 10)
private String zipCode;

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package com.orderflow.ecommerce.exceptions;

import com.orderflow.ecommerce.controllers.exceptions.FieldMessage;
import lombok.Getter;

import java.util.ArrayList;
import java.util.List;

@Getter
public class DuplicateResourceValidationException extends RuntimeException {

private final List<FieldMessage> errors = new ArrayList<>();

public DuplicateResourceValidationException(List<FieldMessage> errors, String message) {
super(message);
this.errors.addAll(errors);
}

public void addError(String fieldName, String message) {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • I believe addError is unnecessary, since the constructor already receives the complete list. Why did you decide to implement it?

errors.add(new FieldMessage(fieldName, message));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.orderflow.ecommerce.repositories;

import com.orderflow.ecommerce.entities.User;
import org.springframework.data.jpa.repository.JpaRepository;

import java.util.Optional;

public interface UserRepository extends JpaRepository<User, Long> {

Optional<User> findByEmailIgnoreCase(String email);

boolean existsByEmail(String email);
boolean existsByEmailAndIdNot(String email, Long id);

boolean existsByTaxId(String taxId);
boolean existsByTaxIdAndIdNot(String taxId, Long id);
}
Loading