Skip to content
Merged
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
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,6 @@ RUN ./mvnw clean install

FROM eclipse-temurin:21-jdk-alpine

COPY --from=build ./target/NoteHub-2.0.0.jar app.jar
COPY --from=build ./target/NoteHub-2.0.1.jar app.jar

ENTRYPOINT ["java", "-jar", "app.jar"]
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@
</div>
<br>
<div align="center">
<a href="https://github.com/notehubbr/notehub-api/releases/tag/v2.0">
<img width="100px" height="25px" src="https://img.shields.io/badge/notehub-2.0-7c3aed">
<a href="https://github.com/notehubbr/notehub-api/releases/tag/v2.0.1">
<img width="100px" height="25px" src="https://img.shields.io/badge/notehub-2.0.1-7c3aed">
</a>
</div>

Expand Down
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
</parent>
<groupId>br.com.notehub</groupId>
<artifactId>NoteHub</artifactId>
<version>2.0.0</version>
<version>2.0.1</version>
<name>NoteHub</name>
<description>https://notehub.com.br</description>
<url/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
import br.com.notehub.domain.user.User;
import br.com.notehub.domain.user.UserRepository;
import br.com.notehub.domain.user.UserService;
import br.com.notehub.infra.exception.CustomExceptions;
import jakarta.annotation.Nullable;
import jakarta.persistence.EntityNotFoundException;
import lombok.RequiredArgsConstructor;
Expand All @@ -34,6 +33,8 @@
import java.util.function.Function;
import java.util.stream.Collectors;

import static br.com.notehub.infra.exception.CustomExceptions.*;

@Component
@RequiredArgsConstructor
public class UserServiceImpl implements UserService {
Expand All @@ -46,26 +47,33 @@ public class UserServiceImpl implements UserService {
private final PasswordEncoder encoder;
private final Counter counter;

private void validateGif(User user, String img, String field) {
if (img == null || !img.endsWith(".gif")) return;
if (field.equals("banner")) throw new GifNotAllowedException("banner", "GIFs são proibidos como banner.");
if (!user.isSponsor()) throw new GifNotAllowedException("avatar", "GIFs apenas para patrocinadores.");
}

@SneakyThrows
private <T> void changeField(UUID idFromToken, String field, Function<User, T> getter, Consumer<User> setter) {
User user = repository.findById(idFromToken).orElseThrow(EntityNotFoundException::new);
T oldValue = getter.apply(user);
setter.accept(user);
T newValue = getter.apply(user);
if (Objects.equals(oldValue, newValue)) return;
if (user.isBlocked() && (field.equals("avatar") || field.equals("banner"))) throw new CustomExceptions.UserBlockedException(field);
if (user.isBlocked() && (field.equals("avatar") || field.equals("banner"))) throw new UserBlockedException(field);
if (field.equals("avatar") || field.equals("banner")) validateGif(user, (String) newValue, field);
repository.save(user);
historian.setHistory(user, field, String.valueOf(oldValue), String.valueOf(newValue));
}

private String validatePassword(String oldPassword, String newPassword) {
if (encoder.matches(newPassword, oldPassword)) throw new CustomExceptions.SamePasswordException();
if (encoder.matches(newPassword, oldPassword)) throw new SamePasswordException();
return encoder.encode(newPassword);
}

private void validateEmail(String oldEmail, String newEmail) {
repository.findByEmail(newEmail).ifPresent(user -> {
if (Objects.equals(oldEmail, newEmail)) throw new CustomExceptions.SameEmailExpection();
if (Objects.equals(oldEmail, newEmail)) throw new SameEmailExpection();
throw new DataIntegrityViolationException("email");
});
}
Expand Down Expand Up @@ -106,7 +114,7 @@ private Page<User> getUserConnections(Pageable pageable, String q, UUID userRequ

private boolean isFollowing(User follower, User following) {
if (Objects.equals(follower.getId(), following.getId())) {
throw new CustomExceptions.SelfFollowException();
throw new SelfFollowException();
}
return following.getFollowers().contains(follower);
}
Expand All @@ -115,7 +123,7 @@ private Subscription validateSubscription(String subscriptionStr) {
try {
return Subscription.from(subscriptionStr);
} catch (IllegalArgumentException e) {
throw new CustomExceptions.SubscriptionException("Inscrição inválida.");
throw new SubscriptionException("Inscrição inválida.");
}
}

Expand Down Expand Up @@ -237,7 +245,7 @@ public void disallowSubscription(UUID idFromToken, String subscriptionStr) {
public void follow(UUID idFromToken, String username) {
User follower = repository.findByIdWithFollowersAndFollowing(idFromToken).orElseThrow(EntityNotFoundException::new);
User following = repository.findByUsernameWithFollowersAndFollowing(username).orElseThrow(EntityNotFoundException::new);
if (isFollowing(follower, following)) throw new CustomExceptions.AlreadyFollowingException();
if (isFollowing(follower, following)) throw new AlreadyFollowingException();
counter.updateFollowersAndFollowingCount(follower, following, true);
notifier.notify(follower, following, follower, MessageNotification.of(follower));
}
Expand All @@ -247,7 +255,7 @@ public void follow(UUID idFromToken, String username) {
public void unfollow(UUID idFromToken, String username) {
User follower = repository.findByIdWithFollowersAndFollowing(idFromToken).orElseThrow(EntityNotFoundException::new);
User following = repository.findByUsernameWithFollowersAndFollowing(username).orElseThrow(EntityNotFoundException::new);
if (!isFollowing(follower, following)) throw new CustomExceptions.NotFollowingException();
if (!isFollowing(follower, following)) throw new NotFollowingException();
counter.updateFollowersAndFollowingCount(follower, following, false);
}

Expand Down
69 changes: 38 additions & 31 deletions src/main/java/br/com/notehub/infra/exception/ControllerAdvice.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import com.auth0.jwt.exceptions.JWTCreationException;
import com.auth0.jwt.exceptions.JWTDecodeException;
import com.auth0.jwt.exceptions.TokenExpiredException;
import com.stripe.exception.StripeException;
import jakarta.persistence.EntityExistsException;
import jakarta.persistence.EntityNotFoundException;
import org.springframework.dao.DataIntegrityViolationException;
Expand All @@ -24,6 +23,8 @@
import java.util.ArrayList;
import java.util.List;

import static br.com.notehub.infra.exception.CustomExceptions.*;

@RestControllerAdvice
public class ControllerAdvice {

Expand All @@ -40,43 +41,43 @@ private ResponseEntity<List<CustomResponse>> handleMethdArgumentNotValidExceptio
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(response);
}

@ExceptionHandler(CustomExceptions.CustomStripeException.class)
private ResponseEntity<List<CustomResponse>> handleStripeException(CustomExceptions.CustomStripeException ex) {
@ExceptionHandler(CustomStripeException.class)
private ResponseEntity<List<CustomResponse>> handleStripeException(CustomStripeException ex) {
List<FieldError> errors = new ArrayList<>();
errors.add(new FieldError("Payment", "Payment", ex.getMessage()));
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(errors.stream().map(CustomResponse::new).toList());
}

@ExceptionHandler(CustomExceptions.InvalidSecretException.class)
private ResponseEntity<List<CustomResponse>> handleInvalidSecretException(CustomExceptions.InvalidSecretException ex) {
@ExceptionHandler(InvalidSecretException.class)
private ResponseEntity<List<CustomResponse>> handleInvalidSecretException(InvalidSecretException ex) {
List<FieldError> errors = new ArrayList<>();
errors.add(new FieldError("Headers", "Headers", ex.getMessage()));
return ResponseEntity.status(HttpStatus.FORBIDDEN).body(errors.stream().map(CustomResponse::new).toList());
}

@ExceptionHandler(CustomExceptions.MissingDeviceException.class)
private ResponseEntity<List<CustomResponse>> handleMissingDeviceException(CustomExceptions.MissingDeviceException ex) {
@ExceptionHandler(MissingDeviceException.class)
private ResponseEntity<List<CustomResponse>> handleMissingDeviceException(MissingDeviceException ex) {
List<FieldError> errors = new ArrayList<>();
errors.add(new FieldError("Headers", "Headers", ex.getMessage()));
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(errors.stream().map(CustomResponse::new).toList());
}

@ExceptionHandler(CustomExceptions.InvalidDeviceException.class)
private ResponseEntity<List<CustomResponse>> handleInvalidDeviceException(CustomExceptions.InvalidDeviceException ex) {
@ExceptionHandler(InvalidDeviceException.class)
private ResponseEntity<List<CustomResponse>> handleInvalidDeviceException(InvalidDeviceException ex) {
List<FieldError> errors = new ArrayList<>();
errors.add(new FieldError("Headers", "Headers", ex.getMessage()));
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(errors.stream().map(CustomResponse::new).toList());
}

@ExceptionHandler(CustomExceptions.MissingRefreshToken.class)
private ResponseEntity<List<CustomResponse>> handleMissingRefreshTokenException(CustomExceptions.MissingRefreshToken ex) {
@ExceptionHandler(MissingRefreshToken.class)
private ResponseEntity<List<CustomResponse>> handleMissingRefreshTokenException(MissingRefreshToken ex) {
List<FieldError> errors = new ArrayList<>();
errors.add(new FieldError("Headers", "Headers", ex.getMessage()));
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(errors.stream().map(CustomResponse::new).toList());
}

@ExceptionHandler(CustomExceptions.InvalidRefreshTokenException.class)
private ResponseEntity<List<CustomResponse>> handleInvalidRefreshTokenException(CustomExceptions.InvalidRefreshTokenException ex) {
@ExceptionHandler(InvalidRefreshTokenException.class)
private ResponseEntity<List<CustomResponse>> handleInvalidRefreshTokenException(InvalidRefreshTokenException ex) {
List<FieldError> errors = new ArrayList<>();
errors.add(new FieldError("Headers", "Headers", ex.getMessage()));
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(errors.stream().map(CustomResponse::new).toList());
Expand Down Expand Up @@ -176,8 +177,8 @@ private ResponseEntity<List<CustomResponse>> handleIllegalStateException(Illegal
return ResponseEntity.status(HttpStatus.FORBIDDEN).body(errors.stream().map(CustomResponse::new).toList());
}

@ExceptionHandler(CustomExceptions.UserBlockedException.class)
private ResponseEntity<List<CustomResponse>> handleUserBlockedException(CustomExceptions.UserBlockedException ex) {
@ExceptionHandler(UserBlockedException.class)
private ResponseEntity<List<CustomResponse>> handleUserBlockedException(UserBlockedException ex) {
List<FieldError> errors = new ArrayList<>();
return switch (ex.getMessage()) {
case "avatar" -> {
Expand Down Expand Up @@ -213,60 +214,66 @@ private ResponseEntity<List<CustomResponse>> handleTokenExpiredException(TokenEx
return ResponseEntity.status(HttpStatus.FORBIDDEN).body(errors.stream().map(CustomResponse::new).toList());
}

@ExceptionHandler(CustomExceptions.ScopeNotAllowedException.class)
private ResponseEntity<List<CustomResponse>> handleScopeNotAllowedException(CustomExceptions.ScopeNotAllowedException ex) {
@ExceptionHandler(ScopeNotAllowedException.class)
private ResponseEntity<List<CustomResponse>> handleScopeNotAllowedException(ScopeNotAllowedException ex) {
List<FieldError> errors = new ArrayList<>();
errors.add(new FieldError("token", "scope", ex.getMessage()));
return ResponseEntity.status(HttpStatus.FORBIDDEN).body(errors.stream().map(CustomResponse::new).toList());
}

@ExceptionHandler(CustomExceptions.SamePasswordException.class)
private ResponseEntity<List<CustomResponse>> handleSamePasswordException(CustomExceptions.SamePasswordException ex) {
@ExceptionHandler(SamePasswordException.class)
private ResponseEntity<List<CustomResponse>> handleSamePasswordException(SamePasswordException ex) {
List<FieldError> errors = new ArrayList<>();
errors.add(new FieldError("user", "password", ex.getMessage()));
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(errors.stream().map(CustomResponse::new).toList());
}

@ExceptionHandler(CustomExceptions.SameEmailExpection.class)
private ResponseEntity<List<CustomResponse>> handleSameEmailExpection(CustomExceptions.SameEmailExpection ex) {
@ExceptionHandler(SameEmailExpection.class)
private ResponseEntity<List<CustomResponse>> handleSameEmailExpection(SameEmailExpection ex) {
List<FieldError> errors = new ArrayList<>();
errors.add(new FieldError("user", "email", ex.getMessage()));
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(errors.stream().map(CustomResponse::new).toList());
}

@ExceptionHandler(CustomExceptions.SelfFollowException.class)
private ResponseEntity<List<CustomResponse>> handleSelfFollowException(CustomExceptions.SelfFollowException ex) {
@ExceptionHandler(SelfFollowException.class)
private ResponseEntity<List<CustomResponse>> handleSelfFollowException(SelfFollowException ex) {
List<FieldError> errors = new ArrayList<>();
errors.add(new FieldError("user", "user", ex.getMessage()));
return ResponseEntity.status(HttpStatus.FORBIDDEN).body(errors.stream().map(CustomResponse::new).toList());
}

@ExceptionHandler(CustomExceptions.AlreadyFollowingException.class)
private ResponseEntity<List<CustomResponse>> handleAlreadyFollowingException(CustomExceptions.AlreadyFollowingException ex) {
@ExceptionHandler(AlreadyFollowingException.class)
private ResponseEntity<List<CustomResponse>> handleAlreadyFollowingException(AlreadyFollowingException ex) {
List<FieldError> errors = new ArrayList<>();
errors.add(new FieldError("user", "user", ex.getMessage()));
return ResponseEntity.status(HttpStatus.CONFLICT).body(errors.stream().map(CustomResponse::new).toList());
}

@ExceptionHandler(CustomExceptions.NotFollowingException.class)
private ResponseEntity<List<CustomResponse>> handleNotFollowingException(CustomExceptions.NotFollowingException ex) {
@ExceptionHandler(NotFollowingException.class)
private ResponseEntity<List<CustomResponse>> handleNotFollowingException(NotFollowingException ex) {
List<FieldError> errors = new ArrayList<>();
errors.add(new FieldError("user", "user", ex.getMessage()));
return ResponseEntity.status(HttpStatus.CONFLICT).body(errors.stream().map(CustomResponse::new).toList());
}

@ExceptionHandler(CustomExceptions.HostNotAllowedException.class)
private ResponseEntity<List<CustomResponse>> handleHostNotAllowedException(CustomExceptions.HostNotAllowedException ex) {
@ExceptionHandler(HostNotAllowedException.class)
private ResponseEntity<List<CustomResponse>> handleHostNotAllowedException(HostNotAllowedException ex) {
List<FieldError> errors = new ArrayList<>();
errors.add(new FieldError("user", "host", ex.getMessage()));
return ResponseEntity.status(HttpStatus.FORBIDDEN).body(errors.stream().map(CustomResponse::new).toList());
}

@ExceptionHandler(CustomExceptions.SubscriptionException.class)
private ResponseEntity<List<CustomResponse>> handleSubscriptionException(CustomExceptions.SubscriptionException ex) {
@ExceptionHandler(SubscriptionException.class)
private ResponseEntity<List<CustomResponse>> handleSubscriptionException(SubscriptionException ex) {
List<FieldError> errors = new ArrayList<>();
errors.add(new FieldError("parameter", "subscription", ex.getMessage()));
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(errors.stream().map(CustomResponse::new).toList());
}

@ExceptionHandler(GifNotAllowedException.class)
private ResponseEntity<List<CustomResponse>> handleForbiddenImageFormatException(GifNotAllowedException ex) {
FieldError error = new FieldError("user", ex.getField(), ex.getMessage());
return ResponseEntity.status(HttpStatus.FORBIDDEN).body(List.of(new CustomResponse(error)));
}

}
13 changes: 13 additions & 0 deletions src/main/java/br/com/notehub/infra/exception/CustomExceptions.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package br.com.notehub.infra.exception;

import com.stripe.exception.StripeException;
import lombok.Getter;

import java.util.UUID;

Expand Down Expand Up @@ -112,4 +113,16 @@ public SubscriptionException(String message) {
}
}

@Getter
public static class GifNotAllowedException extends BusinessException {

private final String field;

public GifNotAllowedException(String field, String message) {
super(message);
this.field = field;
}

}

}