-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #66 from L1nkWave/feature/LWB-44_delete-user-account
feature/LWB-44_delete-user-account
- Loading branch information
Showing
26 changed files
with
578 additions
and
110 deletions.
There are no files selected for viewing
4 changes: 4 additions & 0 deletions
4
backend/auth-service/src/main/java/org/linkwave/auth/dto/UserDeleteRequest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
package org.linkwave.auth.dto; | ||
|
||
public record UserDeleteRequest(String password) { | ||
} |
37 changes: 29 additions & 8 deletions
37
backend/auth-service/src/main/java/org/linkwave/auth/entity/User.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
9 changes: 9 additions & 0 deletions
9
backend/auth-service/src/main/java/org/linkwave/auth/exception/UserNotFoundException.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
package org.linkwave.auth.exception; | ||
|
||
import org.springframework.security.core.AuthenticationException; | ||
|
||
public class UserNotFoundException extends AuthenticationException { | ||
public UserNotFoundException() { | ||
super("User not found"); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
79 changes: 79 additions & 0 deletions
79
...end/auth-service/src/main/java/org/linkwave/auth/security/filter/JwtDeleteUserFilter.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
package org.linkwave.auth.security.filter; | ||
|
||
import com.fasterxml.jackson.databind.ObjectMapper; | ||
import jakarta.servlet.FilterChain; | ||
import jakarta.servlet.ServletException; | ||
import jakarta.servlet.http.HttpServletRequest; | ||
import jakarta.servlet.http.HttpServletResponse; | ||
import lombok.RequiredArgsConstructor; | ||
import org.linkwave.auth.dto.UserDeleteRequest; | ||
import org.linkwave.auth.security.UnAuthorizedAuthenticationEntryPoint; | ||
import org.linkwave.auth.service.UserService; | ||
import org.linkwave.shared.auth.JwtAccessParser; | ||
import org.linkwave.shared.auth.Token; | ||
import org.linkwave.shared.utils.Bearers; | ||
import org.springframework.http.HttpHeaders; | ||
import org.springframework.http.HttpMethod; | ||
import org.springframework.lang.NonNull; | ||
import org.springframework.security.authentication.BadCredentialsException; | ||
import org.springframework.security.core.AuthenticationException; | ||
import org.springframework.security.web.AuthenticationEntryPoint; | ||
import org.springframework.security.web.util.matcher.AntPathRequestMatcher; | ||
import org.springframework.security.web.util.matcher.RequestMatcher; | ||
import org.springframework.web.filter.OncePerRequestFilter; | ||
|
||
import java.io.IOException; | ||
|
||
@RequiredArgsConstructor | ||
public class JwtDeleteUserFilter extends OncePerRequestFilter { | ||
|
||
private final RequestMatcher matcher = new AntPathRequestMatcher("/api/v1/users", HttpMethod.DELETE.name()); | ||
|
||
private final ObjectMapper objectMapper; | ||
private final AuthenticationEntryPoint authenticationEntryPoint; | ||
private final JwtAccessParser jwtAccessParser; | ||
private final UserService userService; | ||
|
||
public JwtDeleteUserFilter(ObjectMapper objectMapper, JwtAccessParser jwtAccessParser, UserService userService) { | ||
this.objectMapper = objectMapper; | ||
this.jwtAccessParser = jwtAccessParser; | ||
this.userService = userService; | ||
this.authenticationEntryPoint = new UnAuthorizedAuthenticationEntryPoint(objectMapper); | ||
} | ||
|
||
@Override | ||
protected void doFilterInternal(@NonNull HttpServletRequest request, | ||
@NonNull HttpServletResponse response, | ||
@NonNull FilterChain filterChain) throws ServletException, IOException { | ||
if (!matcher.matches(request)) { | ||
filterChain.doFilter(request, response); | ||
return; | ||
} | ||
|
||
final String header = request.getHeader(HttpHeaders.AUTHORIZATION); | ||
|
||
try { | ||
final String password; | ||
try { | ||
final UserDeleteRequest deleteRequest = objectMapper.readValue(request.getInputStream(), UserDeleteRequest.class); | ||
password = deleteRequest.password(); | ||
} catch (IOException e) { | ||
throw new BadCredentialsException("Invalid request body"); | ||
} | ||
|
||
if (header == null || !header.startsWith(Bearers.BEARER_PREFIX)) { | ||
throw new BadCredentialsException("Bearer is not present"); | ||
} | ||
|
||
final Token accessToken = jwtAccessParser.parse(header.substring(Bearers.TOKEN_START_POSITION)); | ||
userService.deleteAccount(accessToken, password); | ||
|
||
response.setContentLength(0); | ||
response.setStatus(HttpServletResponse.SC_NO_CONTENT); | ||
|
||
} catch (AuthenticationException e) { | ||
authenticationEntryPoint.commence(request, response, e); | ||
} | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
46 changes: 46 additions & 0 deletions
46
backend/auth-service/src/main/java/org/linkwave/auth/service/UserService.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
package org.linkwave.auth.service; | ||
|
||
import lombok.RequiredArgsConstructor; | ||
import org.linkwave.auth.entity.DeactivatedToken; | ||
import org.linkwave.auth.entity.User; | ||
import org.linkwave.auth.exception.UserNotFoundException; | ||
import org.linkwave.auth.repository.DeactivatedTokenRepository; | ||
import org.linkwave.auth.repository.UserRepository; | ||
import org.linkwave.shared.auth.Token; | ||
import org.springframework.security.authentication.BadCredentialsException; | ||
import org.springframework.security.authentication.CredentialsExpiredException; | ||
import org.springframework.security.crypto.password.PasswordEncoder; | ||
import org.springframework.stereotype.Service; | ||
import org.springframework.transaction.annotation.Transactional; | ||
|
||
import java.time.ZonedDateTime; | ||
|
||
@Service | ||
@RequiredArgsConstructor | ||
public class UserService { | ||
|
||
private final DeactivatedTokenRepository deactivatedTokenRepository; | ||
private final UserRepository userRepository; | ||
private final PasswordEncoder passwordEncoder; | ||
|
||
@Transactional | ||
public void deleteAccount(Token accessToken, String userPassword) { | ||
if (accessToken == null || deactivatedTokenRepository.existsById(accessToken.id())) { | ||
throw new CredentialsExpiredException("Access token is unavailable"); | ||
} | ||
|
||
final User user = userRepository.findById(accessToken.userId()).orElseThrow(UserNotFoundException::new); | ||
if (!passwordEncoder.matches(userPassword, user.getPassword())) { | ||
throw new BadCredentialsException("Credentials not valid"); | ||
} | ||
|
||
final var deactivatedToken = new DeactivatedToken(accessToken.id(), accessToken.expireAt()); | ||
deactivatedTokenRepository.save(deactivatedToken); | ||
|
||
user.setDeleted(true); | ||
user.setUsername(null); | ||
user.setOnline(false); | ||
user.setLastSeen(ZonedDateTime.now()); | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.