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
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.stream.Collectors;

@Log4j2
@Component
Expand All @@ -20,8 +21,14 @@ public class JwtProvider {

public String generateJwtToken(Authentication authentication) {
UserDatailsImpl userPrincipal = (UserDatailsImpl) authentication.getPrincipal();

final String roles = userPrincipal.getAuthorities().stream().map(role -> {
return role.getAuthority();
}).collect(Collectors.joining());

return Jwts.builder()
.setSubject(userPrincipal.getUserId())
.claim("roles", roles)
.setIssuedAt(new Date())
.setExpiration(new Date((new Date()).getTime() + jwtExpirationMs))
.signWith(io.jsonwebtoken.SignatureAlgorithm.HS512, jwtSecret)
Expand Down
14 changes: 14 additions & 0 deletions transacional/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,20 @@
<sonar.coverage.jacoco.xmlReportPaths>target/site/jacoco/jacoco.xml</sonar.coverage.jacoco.xmlReportPaths>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.1</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package com.example.rent.config.security;

import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import java.io.IOException;

@Component
public class JwtAuthenticationFilter extends OncePerRequestFilter {

@Autowired
private JwtProvider jwtProvider;

@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
String token = extractToken(request);
if (token != null && jwtProvider.validateToken(token)) {
String userId = jwtProvider.getSubjectFromToken(token);
logger.info("username extraído do token: " + userId);

String roleStr = jwtProvider.getClaimNameJwt(token, "roles");
UserDetails userDetails = UserDatailsImpl.build(userId, roleStr);
logger.info("user details encontrado: " + userDetails);

UsernamePasswordAuthenticationToken authentication =
new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());

SecurityContextHolder.getContext().setAuthentication(authentication);
}

filterChain.doFilter(request, response);

}

private String extractToken(HttpServletRequest request) {
String authHeader = request.getHeader("Authorization");
if (authHeader != null && authHeader.startsWith("Bearer ")) {
return authHeader.substring(7);
}
return null;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package com.example.rent.config.security;

import io.jsonwebtoken.*;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Log4j2
@Component
public class JwtProvider {

@Value( "${ead.auth.jwtSecret}")
private String jwtSecret;

public String getSubjectFromToken(String token) {
return Jwts.parser()
.setSigningKey(jwtSecret)
.parseClaimsJws(token)
.getBody()
.getSubject();
}

public String getClaimNameJwt(String token, String claimName) {
return Jwts.parser().setSigningKey(jwtSecret).parseClaimsJws(token).getBody().get(claimName, String.class);
}

public boolean validateToken(String authToken) {
try {
Jwts.parser().setSigningKey(jwtSecret).parseClaimsJws(authToken);
return true;

} catch (SignatureException e) {
log.error("Invalid JWT signature: {}", e.getMessage());
} catch (MalformedJwtException e) {
log.error("Invalid JWT token: {}", e.getMessage());
} catch (ExpiredJwtException e) {
log.error("JWT token is expired: {}", e.getMessage());
} catch (UnsupportedJwtException e) {
log.error("JWT token is unsupported: {}", e.getMessage());
} catch (IllegalArgumentException e) {
log.error("JWT claims string is empty: {}", e.getMessage());
}
return false;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package com.example.rent.config.security;

import jakarta.ws.rs.HttpMethod;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

@Configuration
@EnableMethodSecurity
public class SecurityConfig {

@Autowired
private JwtAuthenticationFilter jwtAuthenticationFilter;

@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.csrf(AbstractHttpConfigurer::disable)
.authorizeHttpRequests(auth -> auth
.requestMatchers(HttpMethod.POST, "/users/**", "/auth/**").permitAll()
.requestMatchers(HttpMethod.GET, "/accommodations", "/accommodations/**", "/images/**").permitAll()
.anyRequest().authenticated()
)
.addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class)
.httpBasic(Customizer.withDefaults());

return http.build();
}

@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package com.example.rent.config.security;

import org.springframework.security.core.Authentication;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;

public class SecurityUtil {

public static String getAuthenticatedUserId() {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();

if (authentication != null && authentication.getPrincipal() instanceof UserDatailsImpl userDetails) {
return userDetails.getUserId();
}

throw new RuntimeException("Usuário não autenticado!");
}

public static boolean isAuthenticatedAdmin() {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();

if (authentication != null && authentication.getAuthorities().contains(new SimpleGrantedAuthority("ROLE_ADMINISTRATOR"))) {
return true;
}
return false;
}

public static boolean isOwnerOrAdmin(String resourceUserId) {
String authenticatedUserId = getAuthenticatedUserId();
return isAuthenticatedAdmin() || authenticatedUserId.equals(resourceUserId);
}


}
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package com.example.rent.config.security;

import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;

import java.io.Serial;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;

public class UserDatailsImpl implements UserDetails {

@Serial
private static final long serialVersionUID = 4735505087197006457L;
private String userId;
private Collection<? extends GrantedAuthority> authorities;

public UserDatailsImpl(String userId, Collection<? extends GrantedAuthority> authorities) {
this.userId = userId;
this.authorities = authorities;
}

public static UserDatailsImpl build(String userId, String roleStr) {
List<GrantedAuthority> authorities = Arrays.stream(roleStr.split(","))
.map(SimpleGrantedAuthority::new)
.collect(Collectors.toList());

return new UserDatailsImpl(
userId,
authorities
);
}

@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return this.authorities;
}

@Override
public String getPassword() {
return null;
}

@Override
public String getUsername() {
return null;
}

@Override
public boolean isAccountNonExpired() {
return true;
}

@Override
public boolean isAccountNonLocked() {
return true;
}

@Override
public boolean isCredentialsNonExpired() {
return true;
}

@Override
public boolean isEnabled() {
return true;
}

public String getUserId() {
return userId;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;

@JsonIgnoreProperties(ignoreUnknown = true)
public record AccommodationDto(Double price, int maxOccupancy) {
public record AccommodationDto(String id, Double price, int maxOccupancy) {
}

Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@
import java.time.LocalDate;
import java.util.List;

public record BookingDto(Long accommodationId, List<Long> guestIds, LocalDate intialDate, LocalDate endDate) {
public record BookingDto(String accommodationId, List<String> guestIds, LocalDate intialDate, LocalDate endDate) {
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;

@JsonIgnoreProperties(ignoreUnknown = true)
public record UserDto(String name, String email, UserType type) {
public record UserDto(String id, String name, String email, UserType type) {

}

Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import lombok.NoArgsConstructor;


import java.io.Serial;
import java.io.Serializable;

@Entity
Expand All @@ -17,9 +18,11 @@
@Builder
public class Accommodation implements Serializable {

@Serial
private static final long serialVersionUID = 6742147475962430968L;

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String id;

private Double price;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
import lombok.Data;
import lombok.NoArgsConstructor;

import java.io.Serial;
import java.io.Serializable;
import java.util.List;

@Entity
@Data
Expand All @@ -17,15 +17,18 @@
@Builder
public class User implements Serializable {

@Serial
private static final long serialVersionUID = -9206949953784522451L;

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String id;

private String name;

private String email;

@Enumerated(EnumType.STRING)
@Column(name = "user_type", length = 30, nullable = false)
private UserType userType;

}
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@

public enum UserType {

HOST,
ROLE_HOST,

GUEST,
ROLE_GUEST,

ADMINISTRATOR;
ROLE_ADMINISTRATOR;

@JsonCreator
public static UserType fromString(String value) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public static Booking toEntity(BookingDto dto, Accommodation accommodation, List
}

public static BookingDto toDto(Booking booking) {
List<Long> guestIds = booking.getGuests().stream()
List<String> guestIds = booking.getGuests().stream()
.map(guestBooking -> guestBooking.getGuest().getId())
.toList();

Expand Down
Loading