feat: drop lombok and bump to spring 3.5.9

This commit is contained in:
2026-01-14 16:10:38 -03:00
parent af2b37fae9
commit 75e082d64b
28 changed files with 812 additions and 209 deletions
+2 -19
View File
@@ -5,7 +5,7 @@
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.5.7</version>
<version>3.5.9</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
@@ -30,7 +30,7 @@
<!-- Properties -->
<properties>
<java.version>17</java.version>
<java.version>21</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<skip.integration.tests>true</skip.integration.tests>
@@ -132,11 +132,6 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!-- Database -->
<dependency>
@@ -219,18 +214,6 @@
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
@@ -1,7 +1,7 @@
package br.com.tasknoteapp.server.config;
import java.util.Arrays;
import lombok.extern.slf4j.Slf4j;
import java.util.logging.Logger;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.lang.NonNull;
@@ -9,10 +9,11 @@ import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/** This class contains configurations for CORS management. */
@Slf4j
@Configuration
public class CorsConfig implements WebMvcConfigurer {
private static final Logger logger = Logger.getLogger(CorsConfig.class.getName());
@Value("${cors.allowed-origins}")
private String[] allowedOrigins;
@@ -23,8 +24,8 @@ public class CorsConfig implements WebMvcConfigurer {
*/
public void addCorsMappings(@NonNull CorsRegistry registry) {
if (allowedOrigins != null && allowedOrigins.length > 0) {
log.info("CORS policy allowed origins: {}", Arrays.asList(allowedOrigins));
log.debug("CORS policy allowed origins in debug mode: {}", Arrays.asList(allowedOrigins));
logger.info("CORS policy allowed origins: " + Arrays.asList(allowedOrigins));
logger.fine("CORS policy allowed origins in debug mode: " + Arrays.asList(allowedOrigins));
registry
.addMapping("/**")
@@ -3,7 +3,6 @@ package br.com.tasknoteapp.server.config;
import br.com.tasknoteapp.server.filter.JwtAuthenticationFilter;
import br.com.tasknoteapp.server.service.UserService;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
@@ -23,13 +22,17 @@ import org.springframework.security.web.authentication.UsernamePasswordAuthentic
/** This class contains security configurations. */
@Configuration
@EnableWebSecurity
@RequiredArgsConstructor
public class SecurityConfig {
private final UserService userService;
private final JwtAuthenticationFilter jwtAuthenticationFilter;
public SecurityConfig(UserService userService, JwtAuthenticationFilter jwtAuthenticationFilter) {
this.userService = userService;
this.jwtAuthenticationFilter = jwtAuthenticationFilter;
}
/**
* Filters a request to add security checks and configurations.
*
@@ -16,7 +16,6 @@ import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import java.util.Objects;
import lombok.AllArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
@@ -30,11 +29,14 @@ import org.springframework.web.bind.annotation.RestController;
@Tag(
name = "Authentication",
description = "Authentication resources to handle user authentication.")
@AllArgsConstructor
public class AuthenticationController {
private final AuthService authService;
public AuthenticationController(AuthService authService) {
this.authService = authService;
}
/**
* Signup a new user.
*
@@ -7,7 +7,6 @@ import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.tags.Tag;
import java.util.List;
import lombok.AllArgsConstructor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@@ -15,12 +14,15 @@ import org.springframework.web.bind.annotation.RestController;
/** This class provides resources to handle home requests by the client. */
@RestController
@RequestMapping("/rest/home")
@AllArgsConstructor
@Tag(name = "Home", description = "Home resources to handle home page.")
public class HomeController {
private final HomeService homeService;
public HomeController(HomeService homeService) {
this.homeService = homeService;
}
/**
* Get the top 5 tags.
*
@@ -15,7 +15,6 @@ import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import java.util.List;
import lombok.AllArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
@@ -30,12 +29,15 @@ import org.springframework.web.bind.annotation.RestController;
/** This class provides resources to handle notes requests by the client. */
@RestController
@RequestMapping("/rest/notes")
@AllArgsConstructor
@Tag(name = "Notes", description = "Notes resources to handle stored notes.")
public class NoteController {
private final NoteService noteService;
public NoteController(NoteService noteService) {
this.noteService = noteService;
}
/**
* Get all notes.
*
@@ -14,7 +14,6 @@ import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import java.util.List;
import lombok.AllArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
@@ -30,11 +29,14 @@ import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/rest/tasks")
@Tag(name = "Tasks", description = "Tasks resources to handle user tasks and urls.")
@AllArgsConstructor
public class TaskController {
private final TaskService taskService;
public TaskController(TaskService taskService) {
this.taskService = taskService;
}
/**
* Get all tasks.
*
@@ -10,7 +10,6 @@ import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import java.util.List;
import lombok.AllArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PatchMapping;
@@ -21,12 +20,15 @@ import org.springframework.web.bind.annotation.RestController;
/** This class contains resources for handling users admin requests. */
@RestController
@RequestMapping("/rest/users")
@AllArgsConstructor
@Tag(name = "Users", description = "Users resources to handle stored users.")
public class UserController {
private final AuthService authService;
public UserController(AuthService authService) {
this.authService = authService;
}
/**
* Get all users.
*
@@ -9,8 +9,6 @@ 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 io.swagger.v3.oas.annotations.tags.Tag;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
@@ -18,15 +16,17 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/** This class contains resources for handling user sessions. */
@Slf4j
@RestController
@RequestMapping("/rest/user-sessions")
@AllArgsConstructor
@Tag(name = "User Sessions", description = "Resources to handle user sessions.")
public class UserSessionController {
private final UserSessionService userSessionService;
public UserSessionController(UserSessionService userSessionService) {
this.userSessionService = userSessionService;
}
/**
* Refresh an existing user session, generating a new token.
*
@@ -11,16 +11,10 @@ import jakarta.persistence.ManyToOne;
import jakarta.persistence.OneToOne;
import jakarta.persistence.Table;
import java.time.LocalDateTime;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
/** This class represents a note in the database. */
@Data
@Entity
@Table(name = "notes")
@ToString
@EqualsAndHashCode
public class NoteEntity {
@Id
@@ -44,4 +38,96 @@ public class NoteEntity {
@Column(name = "last_update")
private LocalDateTime lastUpdate;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public UserEntity getUser() {
return user;
}
public void setUser(UserEntity user) {
this.user = user;
}
public NoteUrlEntity getNoteUrl() {
return noteUrl;
}
public void setNoteUrl(NoteUrlEntity noteUrl) {
this.noteUrl = noteUrl;
}
public String getTag() {
return tag;
}
public void setTag(String tag) {
this.tag = tag;
}
public LocalDateTime getLastUpdate() {
return lastUpdate;
}
public void setLastUpdate(LocalDateTime lastUpdate) {
this.lastUpdate = lastUpdate;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
NoteEntity that = (NoteEntity) o;
return id != null && id.equals(that.id);
}
@Override
public int hashCode() {
return getClass().hashCode();
}
@Override
public String toString() {
return "NoteEntity{"
+ "id="
+ id
+ ", title='"
+ title
+ '\''
+ ", description='"
+ description
+ '\''
+ ", tag='"
+ tag
+ '\''
+ ", lastUpdate="
+ lastUpdate
+ '}';
}
}
@@ -8,16 +8,10 @@ import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.OneToOne;
import jakarta.persistence.Table;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
/** This class represents a note url in the database. */
@Data
@Entity
@ToString
@Table(name = "note_urls")
@EqualsAndHashCode
public class NoteUrlEntity {
@Id
@@ -29,4 +23,50 @@ public class NoteUrlEntity {
@JoinColumn(name = "note_id", referencedColumnName = "id", nullable = false, updatable = false)
@OneToOne(fetch = FetchType.LAZY)
private NoteEntity note;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public NoteEntity getNote() {
return note;
}
public void setNote(NoteEntity note) {
this.note = note;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
NoteUrlEntity that = (NoteUrlEntity) o;
return id != null && id.equals(that.id);
}
@Override
public int hashCode() {
return getClass().hashCode();
}
@Override
public String toString() {
return "NoteUrlEntity{" + "id=" + id + ", url='" + url + '\'' + '}';
}
}
@@ -11,16 +11,10 @@ import jakarta.persistence.ManyToOne;
import jakarta.persistence.Table;
import java.time.LocalDate;
import java.time.LocalDateTime;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
/** This class represents a task in the database. */
@Data
@Entity
@Table(name = "tasks")
@ToString
@EqualsAndHashCode
public class TaskEntity {
@Id
@@ -47,4 +41,107 @@ public class TaskEntity {
@Column(name = "tag", nullable = true, length = 30)
private String tag;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public Boolean getDone() {
return done;
}
public void setDone(Boolean done) {
this.done = done;
}
public UserEntity getUser() {
return user;
}
public void setUser(UserEntity user) {
this.user = user;
}
public LocalDateTime getLastUpdate() {
return lastUpdate;
}
public void setLastUpdate(LocalDateTime lastUpdate) {
this.lastUpdate = lastUpdate;
}
public LocalDate getDueDate() {
return dueDate;
}
public void setDueDate(LocalDate dueDate) {
this.dueDate = dueDate;
}
public Boolean getHighPriority() {
return highPriority;
}
public void setHighPriority(Boolean highPriority) {
this.highPriority = highPriority;
}
public String getTag() {
return tag;
}
public void setTag(String tag) {
this.tag = tag;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
TaskEntity that = (TaskEntity) o;
return id != null && id.equals(that.id);
}
@Override
public int hashCode() {
return getClass().hashCode();
}
@Override
public String toString() {
return "TaskEntity{"
+ "id="
+ id
+ ", description='"
+ description
+ '\''
+ ", done="
+ done
+ ", lastUpdate="
+ lastUpdate
+ ", dueDate="
+ dueDate
+ ", highPriority="
+ highPriority
+ ", tag='"
+ tag
+ '\''
+ '}';
}
}
@@ -3,17 +3,41 @@ package br.com.tasknoteapp.server.entity;
import jakarta.persistence.EmbeddedId;
import jakarta.persistence.Entity;
import jakarta.persistence.Table;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
/** This class represents a task url in the database. */
@Data
@Entity
@ToString
@Table(name = "task_url")
@EqualsAndHashCode
public class TaskUrlEntity {
@EmbeddedId private TaskUrlEntityPk id;
public TaskUrlEntityPk getId() {
return id;
}
public void setId(TaskUrlEntityPk id) {
this.id = id;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
TaskUrlEntity that = (TaskUrlEntity) o;
return id != null && id.equals(that.id);
}
@Override
public int hashCode() {
return getClass().hashCode();
}
@Override
public String toString() {
return "TaskUrlEntity{" + "id=" + id + '}';
}
}
@@ -1,20 +1,60 @@
package br.com.tasknoteapp.server.entity;
import jakarta.persistence.Embeddable;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
/** This class represents a UrlTaskEntity primary key. */
@AllArgsConstructor
@NoArgsConstructor
@Getter
@Setter
@Embeddable
public class TaskUrlEntityPk {
private Long taskId;
private String url;
public TaskUrlEntityPk() {}
public TaskUrlEntityPk(Long taskId, String url) {
this.taskId = taskId;
this.url = url;
}
public Long getTaskId() {
return taskId;
}
public void setTaskId(Long taskId) {
this.taskId = taskId;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
// Equals using both fields
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
TaskUrlEntityPk that = (TaskUrlEntityPk) o;
return url.equals(that.url) && taskId.equals(that.taskId);
}
@Override
public int hashCode() {
int result = taskId != null ? taskId.hashCode() : 0;
result = 31 * result + (url != null ? url.hashCode() : 0);
return result;
}
@Override
public String toString() {
return "TaskUrlEntityPk{" + "taskId=" + taskId + ", url='" + url + '\'' + '}';
}
}
@@ -11,12 +11,10 @@ import java.time.LocalDateTime;
import java.util.Collection;
import java.util.List;
import java.util.UUID;
import lombok.Data;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
/** This class represents a User in the database. */
@Data
@Entity
@Table(name = "users")
public class UserEntity implements UserDetails {
@@ -91,4 +89,110 @@ public class UserEntity implements UserDetails {
public boolean isEnabled() {
return true;
}
// TODO: generate all Getters and Setters
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
@Override
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public Boolean getAdmin() {
return admin;
}
public void setAdmin(Boolean admin) {
this.admin = admin;
}
public LocalDateTime getCreatedAt() {
return createdAt;
}
public void setCreatedAt(LocalDateTime createdAt) {
this.createdAt = createdAt;
}
public LocalDateTime getInactivatedAt() {
return inactivatedAt;
}
public void setInactivatedAt(LocalDateTime inactivatedAt) {
this.inactivatedAt = inactivatedAt;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<TaskEntity> getTasks() {
return tasks;
}
public void setTasks(List<TaskEntity> tasks) {
this.tasks = tasks;
}
public LocalDateTime getEmailConfirmedAt() {
return emailConfirmedAt;
}
public void setEmailConfirmedAt(LocalDateTime emailConfirmedAt) {
this.emailConfirmedAt = emailConfirmedAt;
}
public UUID getEmailUuid() {
return emailUuid;
}
public void setEmailUuid(UUID emailUuid) {
this.emailUuid = emailUuid;
}
public LocalDateTime getResetPasswordExpiration() {
return resetPasswordExpiration;
}
public void setResetPasswordExpiration(LocalDateTime resetPasswordExpiration) {
this.resetPasswordExpiration = resetPasswordExpiration;
}
public String getResetToken() {
return resetToken;
}
public void setResetToken(String resetToken) {
this.resetToken = resetToken;
}
public String getLang() {
return lang;
}
public void setLang(String lang) {
this.lang = lang;
}
}
@@ -10,16 +10,10 @@ import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.Table;
import java.time.LocalDateTime;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
/** This class represents a User Password Limit in the database. */
@Data
@Entity
@Table(name = "user_pwd_limits")
@ToString
@EqualsAndHashCode
public class UserPwdLimitEntity {
@Id
@@ -32,4 +26,57 @@ public class UserPwdLimitEntity {
@JoinColumn(name = "user_id", referencedColumnName = "id", nullable = false, updatable = false)
@ManyToOne(fetch = FetchType.LAZY)
private UserEntity user;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public LocalDateTime getWhenHappened() {
return whenHappened;
}
public void setWhenHappened(LocalDateTime whenHappened) {
this.whenHappened = whenHappened;
}
public UserEntity getUser() {
return user;
}
public void setUser(UserEntity user) {
this.user = user;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
UserPwdLimitEntity that = (UserPwdLimitEntity) o;
return id != null && id.equals(that.id);
}
@Override
public int hashCode() {
return getClass().hashCode();
}
@Override
public String toString() {
return "UserPwdLimitEntity{"
+ "id="
+ id
+ ", whenHappened="
+ whenHappened
+ ", user="
+ (user != null ? user.getId() : null)
+ '}';
}
}
@@ -8,7 +8,6 @@ import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Objects;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.lang.NonNull;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
@@ -20,7 +19,6 @@ import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;
/** This class represents an authentication filter do authenticate requests. */
@Slf4j
@Component
public class JwtAuthenticationFilter extends OncePerRequestFilter {
@@ -3,47 +3,109 @@ package br.com.tasknoteapp.server.request;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.Email;
import jakarta.validation.constraints.NotNull;
import lombok.AllArgsConstructor;
import lombok.EqualsAndHashCode;
import lombok.Setter;
import lombok.ToString;
/** This class represents a login request with user email and password. */
@Schema(description = "Login request with user email and password.")
@Setter
@NotNull
@EqualsAndHashCode
@ToString
@AllArgsConstructor
public class LoginRequest {
@Schema(description = "User email.")
@Email
@NotNull
String email;
private String email;
@Schema(description = "User password.")
@NotNull
String password;
private String password;
@Schema(description = "User password again.")
String passwordAgain;
private String passwordAgain;
@Schema(description = "User language. (Optional, default English)")
String lang;
private String lang;
public LoginRequest() {}
/**
* Constructs a LoginRequest with the specified email and password.
*
* @param email the user email
* @param password the user password
* @param passwordAgain the user password again
* @param lang the user language
*/
public LoginRequest(String email, String password, String passwordAgain, String lang) {
this.email = email;
this.password = password;
this.passwordAgain = passwordAgain;
this.lang = lang;
}
public String email() {
return email.trim().toLowerCase();
}
public void setEmail(String email) {
this.email = email;
}
public String password() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String passwordAgain() {
return passwordAgain;
}
public void setPasswordAgain(String passwordAgain) {
this.passwordAgain = passwordAgain;
}
public String lang() {
return lang;
}
public void setLang(String lang) {
this.lang = lang;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
LoginRequest that = (LoginRequest) o;
return email().equals(that.email()) && password().equals(that.password());
}
@Override
public int hashCode() {
int result = email().hashCode();
result = 31 * result + password().hashCode();
return result;
}
@Override
public String toString() {
return "LoginRequest{"
+ "email='"
+ email
+ '\''
+ ", password='"
+ password
+ '\''
+ ", passwordAgain='"
+ passwordAgain
+ '\''
+ ", lang='"
+ lang
+ '\''
+ '}';
}
}
@@ -3,25 +3,49 @@ package br.com.tasknoteapp.server.request;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.Email;
import jakarta.validation.constraints.NotNull;
import lombok.AllArgsConstructor;
import lombok.EqualsAndHashCode;
import lombok.Setter;
import lombok.ToString;
/** This class represents a login request with user email and password. */
@Schema(description = "Resend confirmation request with user email and password.")
@Setter
@NotNull
@EqualsAndHashCode
@ToString
@AllArgsConstructor
public class ResendConfirmationRequest {
@Schema(description = "User email.")
@Email
@NotNull
String email;
private String email;
public ResendConfirmationRequest() {}
public ResendConfirmationRequest(String email) {
this.email = email;
}
public String email() {
return email.trim().toLowerCase();
}
public void setEmail(String email) {
this.email = email;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
ResendConfirmationRequest that = (ResendConfirmationRequest) o;
return email().equals(that.email());
}
@Override
public int hashCode() {
return email().hashCode();
}
@Override
public String toString() {
return "ResendConfirmationRequest{" + "email='" + email + '\'' + '}';
}
}
@@ -2,11 +2,9 @@ package br.com.tasknoteapp.server.response;
import io.swagger.v3.oas.annotations.media.Schema;
import java.util.List;
import lombok.Getter;
import org.springframework.validation.FieldError;
/** This class represents a validation error exception to be returned in the JSON format. */
@Getter
@Schema(description = "An object containing the error message and the invalid fields")
public class ValidationExceptionResponse {
@@ -30,4 +28,12 @@ public class ValidationExceptionResponse {
.toList();
this.errorMessage = String.format(MESSAGE_TEMPLATE, fields.size());
}
public String getErrorMessage() {
return errorMessage;
}
public List<FieldIssueResponse> getFields() {
return fields;
}
}
@@ -33,8 +33,7 @@ import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.UUID;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import java.util.logging.Logger;
import org.springframework.core.env.Environment;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;
@@ -46,11 +45,11 @@ import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
/** This class contains the implementation for the Auth Service class. */
@Slf4j
@Service
@AllArgsConstructor
public class AuthService {
private static final Logger logger = Logger.getLogger(AuthService.class.getName());
private final UserRepository userRepository;
private final PasswordEncoder passwordEncoder;
@@ -67,6 +66,37 @@ public class AuthService {
private final Environment environment;
/**
* Constructor for AuthService.
*
* @param userRepository UserRepository instance.
* @param passwordEncoder PasswordEncoder instance.
* @param jwtService JwtService instance.
* @param authenticationManager AuthenticationManager instance.
* @param authUtil AuthUtil instance.
* @param userPwdLimitRepository UserPwdLimitRepository instance.
* @param mailgunEmailService MailgunEmailService instance.
* @param environment Environment instance.
*/
public AuthService(
UserRepository userRepository,
PasswordEncoder passwordEncoder,
JwtService jwtService,
AuthenticationManager authenticationManager,
AuthUtil authUtil,
UserPwdLimitRepository userPwdLimitRepository,
MailgunEmailService mailgunEmailService,
Environment environment) {
this.userRepository = userRepository;
this.passwordEncoder = passwordEncoder;
this.jwtService = jwtService;
this.authenticationManager = authenticationManager;
this.authUtil = authUtil;
this.userPwdLimitRepository = userPwdLimitRepository;
this.mailgunEmailService = mailgunEmailService;
this.environment = environment;
}
/**
* Create a new user in the app.
*
@@ -75,7 +105,7 @@ public class AuthService {
*/
@Transactional
public UserResponseWithToken signUpNewUser(LoginRequest newUser) {
log.info("Signing up new user! {}", newUser.email());
logger.info("Signing up new user: " + newUser.email());
if (findByEmail(newUser.email()).isPresent()) {
throw new EmailAlreadyExistsException();
@@ -111,7 +141,7 @@ public class AuthService {
mailgunEmailService.sendNewUser(user);
}
log.info("User created! ID {}", user.getId());
logger.info("User created! ID " + user.getId());
return UserResponseWithToken.fromEntity(user, null, getGravatarImageUrl(newUser.email()));
}
@@ -148,7 +178,7 @@ public class AuthService {
*/
@Transactional
public UserResponseWithToken signInUser(LoginRequest login) {
log.info("Signing in user! {}", login.email());
logger.info("Signing in user: " + login.email());
Optional<UserEntity> userOptional = findByEmail(login.email());
if (userOptional.isEmpty()) {
@@ -167,14 +197,14 @@ public class AuthService {
String token = jwtService.generateToken(user);
log.info("User authenticated! Token {}", token);
logger.info("User authenticated! Token " + token);
userPwdLimitRepository.deleteAllForUser(user.getId());
userRepository.save(user);
return UserResponseWithToken.fromEntity(user, token, getGravatarImageUrl(login.email()));
} catch (BadCredentialsException e) {
log.error("BadCredentialsException when logging in user {}: {}", user.getId(),
e.getMessage());
logger.severe(
"BadCredentialsException when logging in user " + user.getId() + ": " + e.getMessage());
// store attempt
UserPwdLimitEntity pwdLimit = new UserPwdLimitEntity();
@@ -195,29 +225,28 @@ public class AuthService {
public List<UserResponse> getAllUsers() {
Optional<String> currentUserEmail = authUtil.getCurrentUserEmail();
if (currentUserEmail.isEmpty()) {
log.error("Unable to get current user from the request");
logger.severe("Unable to get current user from the request");
throw new UserNotFoundException();
}
Optional<UserEntity> currentUserOpt = findByEmail(currentUserEmail.get());
if (currentUserOpt.isEmpty()) {
log.error("Unable to find user by email with value: {}", currentUserEmail.get());
logger.severe("Unable to find user by email with value: " + currentUserEmail.get());
throw new UserNotFoundException();
}
UserEntity currentUser = currentUserOpt.get();
if (!currentUser.getAdmin()) {
log.warn("User {} not allowed to list users.", currentUser.getId());
logger.warning("User " + currentUser.getId() + " not allowed to list users.");
throw new UserForbiddenException();
}
log.info("Getting all users to user {}", currentUser.getId());
logger.info("Getting all users to user " + currentUser.getId());
List<UserEntity> users = userRepository.findAll();
List<UserResponse> usersResponse = new ArrayList<>(users.size());
users.forEach(
u -> usersResponse.add(UserResponse.fromEntity(u, getGravatarImageUrl(u.getEmail()))));
log.info("{} user(s) found!", usersResponse.size());
logger.info(usersResponse.size() + " user(s) found!");
return usersResponse;
}
@@ -232,11 +261,11 @@ public class AuthService {
String email = currentUserEmail.orElseThrow();
UserEntity currentUser = findByEmail(email).orElseThrow();
log.info("Refreshing current session to user {}", currentUser.getId());
logger.info("Refreshing current session to user " + currentUser.getId());
String token = jwtService.generateToken(currentUser);
log.info("User refreshed! Token {}", token);
logger.info("User refreshed! Token " + token);
return token;
}
@@ -250,7 +279,7 @@ public class AuthService {
String email = currentUserEmail.orElseThrow();
UserEntity currentUser = findByEmail(email).orElseThrow();
log.info("Deleting account for user {}", currentUser.getId());
logger.info("Deleting account for user " + currentUser.getId());
currentUser.setInactivatedAt(LocalDateTime.now());
userPwdLimitRepository.deleteAllForUser(currentUser.getId());
@@ -313,7 +342,7 @@ public class AuthService {
if (emailChanged && hasValidMailgunApiKey()) {
// send email to older and new account
log.info("Email changed from {} to {}", email, patchRequest.email());
logger.info("Email changed from " + email + " to " + patchRequest.email());
mailgunEmailService.sendEmailChangedNotification(currentUser, email);
}
@@ -343,7 +372,7 @@ public class AuthService {
*/
@Transactional
public void confirmUserAccount(String identification) {
log.info("Confirming user email account");
logger.info("Confirming user email account");
UUID uuid = null;
try {
@@ -361,7 +390,7 @@ public class AuthService {
user.setEmailConfirmedAt(LocalDateTime.now());
userRepository.save(user);
log.info("User email address confirmed: {}", identification);
logger.info("User email address confirmed: " + identification);
}
/**
@@ -370,7 +399,7 @@ public class AuthService {
* @param email The email to re-send.
*/
public void resendEmailConfirmation(String email) {
log.info("Re-sending the confirmation email");
logger.info("Re-sending the confirmation email");
Optional<UserEntity> userOptional = userRepository.findByEmail(email);
if (userOptional.isEmpty()) {
@@ -383,7 +412,7 @@ public class AuthService {
mailgunEmailService.sendNewUser(user);
}
log.info("Confirmation email re-sent!");
logger.info("Confirmation email re-sent!");
}
/**
@@ -393,11 +422,11 @@ public class AuthService {
*/
@Transactional
public void resetPasswordForUser(String email) {
log.info("Requesting password reset for email {}", email);
logger.info("Requesting password reset for email " + email);
Optional<UserEntity> userOptional = userRepository.findByEmail(email);
if (userOptional.isEmpty()) {
log.info("No user found with this email {}", email);
logger.info("No user found with this email " + email);
return;
}
@@ -412,7 +441,7 @@ public class AuthService {
mailgunEmailService.sendResetPassword(user);
}
log.info("Password reset request succeeded");
logger.info("Password reset request succeeded");
}
/**
@@ -422,7 +451,7 @@ public class AuthService {
*/
@Transactional
public void confirmResetPasswordForUser(PasswordResetRequest request) {
log.info("Saving new password for token {}", request.token());
logger.info("Saving new password for token " + request.token());
Optional<UserEntity> userOptional = userRepository.findByResetToken(request.token());
if (userOptional.isEmpty()) {
@@ -455,12 +484,12 @@ public class AuthService {
mailgunEmailService.sendPasswordResetConfirmation(user);
}
log.info("New password set for token {}", request.token());
logger.info("New password set for token " + request.token());
}
private Optional<String> getGravatarImageUrl(String email) {
email = email.toLowerCase().trim();
log.info("Current user email: {}", email);
logger.info("Current user email: " + email);
try {
MessageDigest digest = MessageDigest.getInstance("SHA-256");
@@ -474,10 +503,10 @@ public class AuthService {
}
hexString.append(hex);
}
log.debug("Email hashed: {}", hexString);
logger.fine("Email hashed: " + hexString);
return Optional.of(hexString.toString());
} catch (NoSuchAlgorithmException | NullPointerException e) {
log.error("NoSuchAlgorithmException or NullPointerException", e.getMessage());
logger.severe("NoSuchAlgorithmException or NullPointerException: " + e.getMessage());
}
return Optional.empty();
}
@@ -486,15 +515,15 @@ public class AuthService {
Sort sort = Sort.by(Direction.DESC, "whenHappened");
List<UserPwdLimitEntity> userPwdList = userPwdLimitRepository.findAllByUser_id(userId, sort);
log.warn("Login count attempt for user {}: {}", userId, userPwdList.size());
logger.warning("login count attempt for user " + userId + ": " + userPwdList.size());
// if it's more than 3 times in the last 10 minutes, raise timer of 3 hours.
if (userPwdList.size() >= 3) {
UserPwdLimitEntity mostRecent = userPwdList.get(0);
log.warn("Oldest: {}", mostRecent.getWhenHappened());
logger.warning("Oldest: " + mostRecent.getWhenHappened());
Duration duration = Duration.between(mostRecent.getWhenHappened(), LocalDateTime.now());
if (duration.toMinutes() <= 3L) {
log.warn("Wait more {}", (3L - duration.toMinutes()));
logger.warning("Wait more " + (3L - duration.toMinutes()));
throw new MaxLoginLimitAttemptException();
}
}
@@ -5,20 +5,23 @@ import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;
import java.util.stream.Collectors;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
/** This class contains the implementation for the Home Service class. */
@Slf4j
@Service
@AllArgsConstructor
public class HomeService {
private static final Logger logger = Logger.getLogger(HomeService.class.getName());
private final TaskService taskService;
private static final String N_TASKS_FOUND = "{} tasks found!";
private static final String N_TASKS_FOUND = "%d tasks found!";
public HomeService(TaskService taskService) {
this.taskService = taskService;
}
/**
* Get up to 5 most used tags.
@@ -26,10 +29,10 @@ public class HomeService {
* @return List of String with the tags.
*/
public List<String> getTopTasksTag() {
log.info("Getting top tags for the tasks");
logger.info("Getting top tags for the tasks");
List<TaskResponse> tasks = taskService.getTasksByFilter("all");
log.info(N_TASKS_FOUND, tasks.size());
logger.info(String.format(N_TASKS_FOUND, tasks.size()));
Map<String, Integer> tagsCount = new HashMap<>();
for (TaskResponse task : tasks) {
@@ -10,7 +10,7 @@ import br.com.tasknoteapp.server.templates.MailgunTemplateSignUp;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.Objects;
import lombok.extern.slf4j.Slf4j;
import java.util.logging.Logger;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.http.HttpEntity;
@@ -24,10 +24,10 @@ import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.RestTemplate;
/** This service handles email messages for Mailgun. */
@Slf4j
@Service
public class MailgunEmailService {
private static final Logger logger = Logger.getLogger(MailgunEmailService.class.getName());
private final RestTemplate restTemplate;
private final String targetEnv;
private String domain;
@@ -61,7 +61,7 @@ public class MailgunEmailService {
* @param user The user that should be addressed the message.
*/
public void sendNewUser(UserEntity user) {
log.info("Sending message confirming user email address.");
logger.info("Sending message confirming user email address.");
String to = user.getEmail();
String subject = "TaskNote App confirmation email";
@@ -79,7 +79,7 @@ public class MailgunEmailService {
* @param user The user that should be addressed the message.
*/
public void sendResetPassword(UserEntity user) {
log.info("Sending message with password reset link");
logger.info("Sending message with password reset link");
String to = user.getEmail();
String subject = "TaskNote App password reset";
@@ -97,7 +97,7 @@ public class MailgunEmailService {
* @param user The user that should be addressed the message.
*/
public void sendPasswordResetConfirmation(UserEntity user) {
log.info("Sending message with password reset confirmation");
logger.info("Sending message with password reset confirmation");
String to = user.getEmail();
String subject = "TaskNote App password confirmation";
@@ -114,7 +114,7 @@ public class MailgunEmailService {
* @param oldEmail The user previous email
*/
public void sendEmailChangedNotification(UserEntity user, String oldEmail) {
log.info("Sending message with changed email notification");
logger.info("Sending message with changed email notification");
MailgunTemplateEmailChanged emailChanged = new MailgunTemplateEmailChanged();
emailChanged.setEmailFrom(oldEmail);
@@ -151,7 +151,7 @@ public class MailgunEmailService {
mailData.add("template", template.getName());
if (!template.getVariables().isEmpty()) {
mailData.add("h:X-Mailgun-Variables", template.getVariableValuesJson());
log.info("JSON template variables: {}", template.getVariableValuesJson());
logger.info("JSON template variables: " + template.getVariableValuesJson());
}
HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<>(mailData, headers);
@@ -163,9 +163,9 @@ public class MailgunEmailService {
throw new MailServiceException("Failed to send email: " + response.getStatusCode());
}
log.info("Email message send successfully.");
logger.info("Email message send successfully.");
} catch (HttpClientErrorException ex) {
log.error("Unable to send email: {} - {}", ex.getMessage(), ex.getCause());
logger.severe("Unable to send email: " + ex.getMessage() + " - " + ex.getCause());
}
}
@@ -16,16 +16,15 @@ import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import java.util.logging.Logger;
import org.springframework.stereotype.Service;
/** This class implements the NoteService interface methods. */
@Slf4j
@Service
@AllArgsConstructor
public class NoteService {
private static final Logger logger = Logger.getLogger(NoteService.class.getName());
private final NoteRepository noteRepository;
private final AuthService authService;
@@ -34,6 +33,25 @@ public class NoteService {
private final NoteUrlRepository noteUrlRepository;
/**
* Constructor for the NoteService class.
*
* @param noteRepository The repository for note entities.
* @param authService The service for authentication.
* @param authUtil Utility class for authentication-related operations.
* @param noteUrlRepository The repository for note URL entities.
*/
public NoteService(
NoteRepository noteRepository,
AuthService authService,
AuthUtil authUtil,
NoteUrlRepository noteUrlRepository) {
this.noteRepository = noteRepository;
this.authService = authService;
this.authUtil = authUtil;
this.noteUrlRepository = noteUrlRepository;
}
/**
* Get all notes for the current user.
*
@@ -42,10 +60,10 @@ public class NoteService {
public List<NoteResponse> getAllNotes() {
UserEntity user = getCurrentUser();
log.info("Get all notes to user {}", user.getId());
logger.info("Get all notes to user " + user.getId());
List<NoteEntity> notes = noteRepository.findAllByUser_id(user.getId());
log.info("{} notes found!", notes.size());
logger.info(notes.size() + " notes found!");
return notes.stream().map(NoteResponse::fromEntity).toList();
}
@@ -58,14 +76,14 @@ public class NoteService {
*/
public NoteResponse getNoteById(Long noteId) {
UserEntity user = getCurrentUser();
log.info("Get note {} to user {}", noteId, user.getId());
logger.info("Get note " + noteId + " to user " + user.getId());
Optional<NoteEntity> task = noteRepository.findById(noteId);
if (task.isEmpty()) {
throw new NoteNotFoundException();
}
log.info("Note found! Id {}", noteId);
logger.info("Note found! Id " + noteId);
return NoteResponse.fromEntity(task.get());
}
@@ -78,7 +96,7 @@ public class NoteService {
public NoteEntity createNote(NoteRequest noteRequest) {
UserEntity user = getCurrentUser();
log.info("Creating note to user {}", user.getId());
logger.info("Creating note to user " + user.getId());
NoteEntity note = new NoteEntity();
note.setTitle(noteRequest.title());
@@ -88,14 +106,14 @@ public class NoteService {
note.setUser(user);
NoteEntity created = noteRepository.save(note);
log.info("Note created! Id {}", created.getId());
logger.info("Note created! Id " + created.getId());
if (!Objects.isNull(noteRequest.url()) && !noteRequest.url().isEmpty()) {
NoteUrlEntity urlEntity = saveUrl(note, noteRequest.url());
note.setNoteUrl(urlEntity);
}
log.info("Finished note creation!");
logger.info("Finished note creation!");
return created;
}
@@ -110,7 +128,7 @@ public class NoteService {
public NoteResponse patchNote(Long noteId, NotePatchRequest patch) {
UserEntity user = getCurrentUser();
log.info("Patching task {} to user {}", noteId, user.getId());
logger.info("Patching task " + noteId + " to user " + user.getId());
Optional<NoteEntity> note = noteRepository.findById(noteId);
if (note.isEmpty()) {
@@ -131,19 +149,19 @@ public class NoteService {
noteUrlRepository.deleteByNote_id(noteId);
noteUrlRepository.flush();
log.info("URL deleted from task {}", noteId);
logger.info("URL deleted from task " + noteId);
if (!Objects.isNull(patch.url()) && !patch.url().isBlank()) {
NoteUrlEntity urlEntity = saveUrl(noteEntity, patch.url());
noteEntity.setNoteUrl(urlEntity);
} else {
log.info("No urls to patch for task {}", noteId);
logger.info("No urls to patch for task " + noteId);
}
NoteEntity patchedNote = noteRepository.save(noteEntity);
noteRepository.flush();
log.info("Note patched! Id {}", patchedNote.getId());
logger.info("Note patched! Id " + patchedNote.getId());
return NoteResponse.fromEntity(patchedNote);
}
@@ -157,7 +175,7 @@ public class NoteService {
public void deleteNote(Long noteId) {
UserEntity user = getCurrentUser();
log.info("Deleting note {} to user {}", noteId, user.getId());
logger.info("Deleting note " + noteId + " to user " + user.getId());
Optional<NoteEntity> note = noteRepository.findById(noteId);
if (note.isEmpty()) {
@@ -167,14 +185,14 @@ public class NoteService {
NoteUrlEntity noteUrl = note.get().getNoteUrl();
if (!Objects.isNull(noteUrl)) {
noteUrlRepository.delete(noteUrl);
log.info("URL Deleted from task {}", noteId);
logger.info("URL Deleted from task " + noteId);
} else {
log.info("No urls to delete for task {}", noteId);
logger.info("No urls to delete for task " + noteId);
}
noteRepository.delete(note.get());
log.info("Note deleted! Id {}", noteId);
logger.info("Note deleted! Id " + noteId);
}
/**
@@ -186,12 +204,11 @@ public class NoteService {
public List<NoteResponse> searchNotes(String searchTerm) {
UserEntity user = getCurrentUser();
log.info("Searching notes to user {}", user.getId());
logger.info("Searching notes to user " + user.getId());
List<NoteEntity> notes =
noteRepository.findAllBySearchTerm(searchTerm.toUpperCase(), user.getId());
log.info("{} tasks found!", notes.size());
logger.info(notes.size() + " tasks found!");
return notes.stream().map(NoteResponse::fromEntity).toList();
}
@@ -207,7 +224,7 @@ public class NoteService {
noteUrl.setNote(noteEntity);
NoteUrlEntity savedUrl = noteUrlRepository.save(noteUrl);
log.info("URL saved to note {}", noteEntity.getId());
logger.info("URL saved to note " + noteEntity.getId());
return savedUrl;
}
@@ -19,16 +19,15 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import java.util.logging.Logger;
import org.springframework.stereotype.Service;
/** This class contains the implementation for the Task Service class. */
@Slf4j
@Service
@AllArgsConstructor
public class TaskService {
private static final Logger logger = Logger.getLogger(TaskService.class.getName());
private final TaskRepository taskRepository;
private final AuthService authService;
@@ -37,6 +36,25 @@ public class TaskService {
private final TaskUrlRepository taskUrlRepository;
/**
* Constructor for the TaskService class.
*
* @param taskRepository The repository for task entities.
* @param authService The service for authentication.
* @param authUtil Utility class for authentication-related operations.
* @param taskUrlRepository The repository for task URL entities.
*/
public TaskService(
TaskRepository taskRepository,
AuthService authService,
AuthUtil authUtil,
TaskUrlRepository taskUrlRepository) {
this.taskRepository = taskRepository;
this.authService = authService;
this.authUtil = authUtil;
this.taskUrlRepository = taskUrlRepository;
}
/**
* Get all tasks for the current user.
*
@@ -44,10 +62,10 @@ public class TaskService {
*/
public List<TaskResponse> getAllTasks() {
UserEntity user = getCurrentUser();
log.info("Get all tasks to user {}", user.getId());
logger.info("Get all tasks to user " + user.getId());
List<TaskEntity> tasks = taskRepository.findAllByUser_id(user.getId());
log.info("{} tasks found!", tasks.size());
logger.info(tasks.size() + " tasks found!");
return tasks.stream()
.map((TaskEntity tr) -> TaskResponse.fromEntity(tr, getAllTasksUrls(tr.getId())))
@@ -62,14 +80,14 @@ public class TaskService {
*/
public TaskResponse getTaskById(Long taskId) {
UserEntity user = getCurrentUser();
log.info("Get task {} to user {}", taskId, user.getId());
logger.info("Get task " + taskId + " to user " + user.getId());
Optional<TaskEntity> task = taskRepository.findById(taskId);
if (task.isEmpty()) {
throw new TaskNotFoundException();
}
log.info("Task found! Id {}", taskId);
logger.info("Task found! Id " + taskId);
return TaskResponse.fromEntity(task.get(), getAllTasksUrls(taskId));
}
@@ -81,7 +99,7 @@ public class TaskService {
public TaskResponse createTask(TaskRequest taskRequest) {
UserEntity user = getCurrentUser();
log.info("Creating task to user {}", user.getId());
logger.info("Creating task to user " + user.getId());
TaskEntity task = new TaskEntity();
task.setDescription(taskRequest.description());
@@ -99,7 +117,7 @@ public class TaskService {
saveUrls(task, taskRequest.urls());
}
log.info("Task created! Id {}", created.getId());
logger.info("Task created! Id " + created.getId());
return TaskResponse.fromEntity(created, getAllTasksUrls(created.getId()));
}
@@ -114,7 +132,7 @@ public class TaskService {
public TaskResponse patchTask(Long taskId, TaskPatchRequest patch) {
UserEntity user = getCurrentUser();
log.info("Patching task {} to user {}", taskId, user.getId());
logger.info("Patching task " + taskId + " to user " + user.getId());
Optional<TaskEntity> task = taskRepository.findById(taskId);
if (task.isEmpty()) {
@@ -146,9 +164,7 @@ public class TaskService {
TaskEntity patchedTask = taskRepository.save(taskEntity);
log.info("Task patched! Id {}", patchedTask.getId());
logger.info("Task patched! Id " + patchedTask.getId());
return TaskResponse.fromEntity(patchedTask, getAllTasksUrls(taskId));
}
@@ -162,7 +178,7 @@ public class TaskService {
public void deleteTask(Long taskId) {
UserEntity user = getCurrentUser();
log.info("Deleting task {} to user {}", taskId, user.getId());
logger.info("Deleting task " + taskId + " to user " + user.getId());
Optional<TaskEntity> task = taskRepository.findById(taskId);
if (task.isEmpty()) {
@@ -172,14 +188,14 @@ public class TaskService {
List<TaskUrlEntity> urlsToDelete = taskUrlRepository.findAllById_taskId(taskId);
if (!urlsToDelete.isEmpty()) {
taskUrlRepository.deleteAllById_taskId(taskId);
log.info("Deleted {} urls from task {}", urlsToDelete.size(), taskId);
logger.info("Deleted " + urlsToDelete.size() + " urls from task " + taskId);
} else {
log.info("No urls to delete for task {}", taskId);
logger.info("No urls to delete for task " + taskId);
}
taskRepository.delete(task.get());
log.info("Task deleted! Id {}", taskId);
logger.info("Task deleted! Id " + taskId);
}
/**
@@ -191,7 +207,7 @@ public class TaskService {
public List<TaskResponse> searchTasks(String searchTerm) {
UserEntity user = getCurrentUser();
log.info("Searching tasks to user {}", user.getId());
logger.info("Searching tasks to user " + user.getId());
if (Objects.isNull(searchTerm) || searchTerm.isBlank()) {
return List.of();
@@ -199,7 +215,7 @@ public class TaskService {
List<TaskEntity> tasks =
taskRepository.findAllBySearchTerm(searchTerm.toUpperCase(), user.getId());
log.info("{} tasks found!", tasks.size());
logger.info(tasks.size() + " tasks found!");
return tasks.stream()
.map((TaskEntity tr) -> TaskResponse.fromEntity(tr, getAllTasksUrls(tr.getId())))
@@ -270,7 +286,7 @@ public class TaskService {
}
taskUrlRepository.saveAll(tasksUrl);
log.info("Added {} urls from task {}", tasksUrl.size(), taskEntity.getId());
logger.info("Added " + tasksUrl.size() + " urls from task " + taskEntity.getId());
}
private void patchDueDate(TaskEntity taskEntity, TaskPatchRequest patch) {
@@ -279,7 +295,8 @@ public class TaskService {
try {
taskEntity.setDueDate(LocalDate.parse(patch.dueDate()));
} catch (DateTimeParseException e) {
log.error("Unable to parse the provided date: {}: {}", patch.dueDate(), e.getMessage(), e);
logger.severe(
"Unable to parse the provided date: " + patch.dueDate() + ": " + e.getMessage());
}
}
}
@@ -289,9 +306,9 @@ public class TaskService {
List<TaskUrlEntity> urlsToDelete = taskUrlRepository.findAllById_taskId(taskId);
if (!urlsToDelete.isEmpty()) {
taskUrlRepository.deleteAllById_taskId(taskId);
log.info("Deleted {} urls from task {}", urlsToDelete.size(), taskId);
logger.info("Deleted " + urlsToDelete.size() + " urls from task " + taskId);
} else {
log.info("No urls to delete for task {}", taskId);
logger.info("No urls to delete for task " + taskId);
}
if (!Objects.isNull(patch.urls())) {
@@ -299,7 +316,7 @@ public class TaskService {
patch.urls().stream().filter(u -> !u.isBlank()).map(String::trim).toList();
saveUrls(taskEntity, urlListToAdd);
} else {
log.info("No urls to add for task {}", taskId);
logger.info("No urls to add for task " + taskId);
}
}
}
@@ -9,12 +9,10 @@ import br.com.tasknoteapp.server.response.UserResponse;
import jakarta.transaction.Transactional;
import java.util.List;
import java.util.Optional;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;
/** This class contains methods to handle user session and account deletion. */
@Service
@AllArgsConstructor
public class UserSessionService {
private final AuthService authService;
@@ -23,6 +21,20 @@ public class UserSessionService {
private final NoteService noteService;
/**
* Constructor for UserSessionService.
*
* @param authService the authentication service
* @param taskService the task service
* @param noteService the note service
*/
public UserSessionService(
AuthService authService, TaskService taskService, NoteService noteService) {
this.authService = authService;
this.taskService = taskService;
this.noteService = noteService;
}
/**
* Refresh the current user session with a new JWT token.
*
@@ -4,18 +4,20 @@ import br.com.tasknoteapp.server.entity.UserEntity;
import br.com.tasknoteapp.server.repository.UserRepository;
import br.com.tasknoteapp.server.service.UserService;
import java.util.Optional;
import lombok.RequiredArgsConstructor;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.stereotype.Service;
/** This class contains the implementation for the User Service class. */
@Service
@RequiredArgsConstructor
class UserServiceImpl implements UserService {
private final UserRepository userRepository;
public UserServiceImpl(UserRepository userRepository) {
this.userRepository = userRepository;
}
@Override
public UserDetailsService userDetailsService() {
return new UserDetailsService() {
@@ -4,13 +4,11 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
/** This class contains utils methods to handle authentication. */
@Slf4j
@Component
public class AuthUtil {