Changeset 3238007
- Timestamp:
- 01/27/26 14:25:53 (6 months ago)
- Branches:
- main
- Children:
- 16aed54
- Parents:
- b70fbeb
- Files:
-
- 7 added
- 6 edited
-
finkwave/src/main/java/com/ukim/finki/develop/finkwave/controller/AuthController.java (modified) (6 diffs)
-
finkwave/src/main/java/com/ukim/finki/develop/finkwave/controller/GlobalExceptionHandler.java (modified) (1 diff)
-
finkwave/src/main/java/com/ukim/finki/develop/finkwave/exceptions/AuthException.java (added)
-
finkwave/src/main/java/com/ukim/finki/develop/finkwave/exceptions/InvalidCredentialsException.java (added)
-
finkwave/src/main/java/com/ukim/finki/develop/finkwave/exceptions/InvalidFileException.java (added)
-
finkwave/src/main/java/com/ukim/finki/develop/finkwave/exceptions/InvalidTokenException.java (added)
-
finkwave/src/main/java/com/ukim/finki/develop/finkwave/exceptions/UnauthenticatedException.java (added)
-
finkwave/src/main/java/com/ukim/finki/develop/finkwave/exceptions/UserAlreadyExistsException.java (added)
-
finkwave/src/main/java/com/ukim/finki/develop/finkwave/exceptions/UserNotFoundException.java (added)
-
finkwave/src/main/java/com/ukim/finki/develop/finkwave/service/AuthService.java (modified) (9 diffs)
-
finkwave/src/main/java/com/ukim/finki/develop/finkwave/service/RefreshTokenService.java (modified) (3 diffs)
-
frontend/src/pages/Login.tsx (modified) (1 diff)
-
frontend/src/pages/Register.tsx (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
finkwave/src/main/java/com/ukim/finki/develop/finkwave/controller/AuthController.java
rb70fbeb r3238007 1 1 package com.ukim.finki.develop.finkwave.controller; 2 2 3 import java.io.IOException; 3 4 import java.util.Map; 4 5 5 import com.ukim.finki.develop.finkwave.config.AuthProperties;6 import org.springframework.http.HttpStatus;7 6 import org.springframework.http.MediaType; 8 7 import org.springframework.http.ResponseEntity; … … 10 9 import org.springframework.security.core.context.SecurityContextHolder; 11 10 import org.springframework.security.core.userdetails.UserDetails; 12 import org.springframework.web.bind.annotation.*; 13 import org.springframework.web.server.ResponseStatusException; 11 import org.springframework.web.bind.annotation.CookieValue; 12 import org.springframework.web.bind.annotation.GetMapping; 13 import org.springframework.web.bind.annotation.ModelAttribute; 14 import org.springframework.web.bind.annotation.PostMapping; 15 import org.springframework.web.bind.annotation.RequestBody; 16 import org.springframework.web.bind.annotation.RequestMapping; 17 import org.springframework.web.bind.annotation.RestController; 14 18 19 import com.ukim.finki.develop.finkwave.config.AuthProperties; 20 import com.ukim.finki.develop.finkwave.exceptions.InvalidTokenException; 21 import com.ukim.finki.develop.finkwave.exceptions.UnauthenticatedException; 15 22 import com.ukim.finki.develop.finkwave.model.dto.AuthRequestDto; 16 23 import com.ukim.finki.develop.finkwave.model.dto.LoginRequestDto; … … 31 38 public ResponseEntity<Map<String, Object>> register( 32 39 @ModelAttribute AuthRequestDto authRequestDto, 33 HttpServletResponse httpServletResponse){ 34 try { 35 UserResponseDto userResponseDto = authService.registerAndLogIn(httpServletResponse, authRequestDto); 36 return ResponseEntity.ok(Map.of( 37 "user", userResponseDto, 38 "tokenExpiresIn", authProperties.getAccessTokenMaxAge() 39 )); 40 } catch (Exception e){ 41 return ResponseEntity 42 .status(HttpStatus.BAD_REQUEST) 43 .body(Map.of("error", e.getMessage())); 44 } 40 HttpServletResponse httpServletResponse) throws IOException { 41 UserResponseDto userResponseDto = authService.registerAndLogIn(httpServletResponse, authRequestDto); 42 return ResponseEntity.ok(Map.of( 43 "user", userResponseDto, 44 "tokenExpiresIn", authProperties.getAccessTokenMaxAge() 45 )); 45 46 } 46 47 … … 48 49 public ResponseEntity<Map<String, Object>> login( 49 50 @RequestBody LoginRequestDto loginRequestDto, 50 HttpServletResponse httpServletResponse){ 51 try { 52 UserResponseDto userResponseDto = authService.login(httpServletResponse, loginRequestDto); 53 return ResponseEntity.ok(Map.of( 54 "user", userResponseDto, 55 "tokenExpiresIn", authProperties.getAccessTokenMaxAge() 56 ) 57 ); 58 } catch (Exception e){ 59 return ResponseEntity 60 .status(HttpStatus.BAD_REQUEST) 61 .body(Map.of("error", e.getMessage())); 62 } 51 HttpServletResponse httpServletResponse) { 52 UserResponseDto userResponseDto = authService.login(httpServletResponse, loginRequestDto); 53 return ResponseEntity.ok(Map.of( 54 "user", userResponseDto, 55 "tokenExpiresIn", authProperties.getAccessTokenMaxAge() 56 )); 63 57 } 64 65 58 66 59 @PostMapping("/refresh") 67 60 public ResponseEntity<Map<String, Integer>> refresh( 68 61 HttpServletResponse httpServletResponse, 69 @CookieValue(name = "refreshToken", required = false) String refreshToken) {70 if (refreshToken == null) {71 throw new ResponseStatusException(HttpStatus.UNAUTHORIZED, "No credentials");62 @CookieValue(name = "refreshToken", required = false) String refreshToken) { 63 if (refreshToken == null) { 64 throw new InvalidTokenException("No refresh token provided."); 72 65 } 73 66 authService.refreshAccessTokenAndAddCookie(httpServletResponse, refreshToken); … … 80 73 public ResponseEntity<Map<String, String>> logout( 81 74 HttpServletResponse httpServletResponse, 82 @CookieValue(name = "refreshToken", required = false) String refreshToken) {75 @CookieValue(name = "refreshToken", required = false) String refreshToken) { 83 76 authService.clearCookies(httpServletResponse, refreshToken); 84 77 SecurityContextHolder.clearContext(); … … 87 80 88 81 @GetMapping("/user") 89 public ResponseEntity<Map<String, Object>> getUser() {82 public ResponseEntity<Map<String, Object>> getUser() { 90 83 Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); 91 if (authentication == null || !authentication.isAuthenticated()) {92 throw new ResponseStatusException(HttpStatus.UNAUTHORIZED, "Not authenticated");84 if (authentication == null || !authentication.isAuthenticated()) { 85 throw new UnauthenticatedException(); 93 86 } 94 87 Object principal = authentication.getPrincipal(); -
finkwave/src/main/java/com/ukim/finki/develop/finkwave/controller/GlobalExceptionHandler.java
rb70fbeb r3238007 1 1 package com.ukim.finki.develop.finkwave.controller; 2 2 3 import java.util.Map; 4 5 import org.slf4j.Logger; 6 import org.slf4j.LoggerFactory; 3 7 import org.springframework.http.HttpStatus; 4 8 import org.springframework.http.ResponseEntity; 9 import org.springframework.security.core.userdetails.UsernameNotFoundException; 5 10 import org.springframework.web.bind.annotation.ExceptionHandler; 6 11 import org.springframework.web.bind.annotation.RestControllerAdvice; 12 import org.springframework.web.multipart.MaxUploadSizeExceededException; 13 import org.springframework.web.server.ResponseStatusException; 7 14 8 import java.util.HashMap; 9 import java.util.Map; 15 import com.ukim.finki.develop.finkwave.exceptions.AuthException; 10 16 11 17 @RestControllerAdvice 12 18 public class GlobalExceptionHandler { 19 private static final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class); 13 20 14 @ExceptionHandler(RuntimeException.class) 15 public ResponseEntity<Map<String, String>> handleRuntimeException(RuntimeException ex) { 16 Map<String, String> errorMap = new HashMap<>(); 17 errorMap.put("error", ex.getMessage()); 21 @ExceptionHandler(AuthException.class) 22 public ResponseEntity<Map<String, String>> handleAuthException(AuthException ex) { 23 return ResponseEntity 24 .status(ex.getStatus()) 25 .body(Map.of("error", ex.getMessage())); 26 } 18 27 19 return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(errorMap); 28 @ExceptionHandler(UsernameNotFoundException.class) 29 public ResponseEntity<Map<String, String>> handleUsernameNotFound(UsernameNotFoundException ex) { 30 return ResponseEntity 31 .status(HttpStatus.UNAUTHORIZED) 32 .body(Map.of("error", "Invalid credentials.")); 33 } 34 35 @ExceptionHandler(ResponseStatusException.class) 36 public ResponseEntity<Map<String, String>> handleResponseStatusException(ResponseStatusException ex) { 37 logger.error("Response status:", ex); 38 return ResponseEntity 39 .status(ex.getStatusCode()) 40 .body(Map.of("error", ex.getReason() != null ? ex.getReason() : "An error occurred.")); 41 } 42 43 @ExceptionHandler(MaxUploadSizeExceededException.class) 44 public ResponseEntity<Map<String, Object>> handleMaxSize(MaxUploadSizeExceededException ex) { 45 logger.error("Max upload size error:", ex); 46 return ResponseEntity 47 .status(HttpStatus.PAYLOAD_TOO_LARGE) 48 .body(Map.of( 49 "error", "File too large.", 50 "maxSize", "2MB" 51 )); 52 } 53 54 @ExceptionHandler(Exception.class) 55 public ResponseEntity<Map<String, String>> handleGenericException(Exception ex) { 56 logger.error("Unexpected error occurred:", ex); 57 return ResponseEntity 58 .status(HttpStatus.INTERNAL_SERVER_ERROR) 59 .body(Map.of("error", "An unexpected error occurred.")); 20 60 } 21 61 } -
finkwave/src/main/java/com/ukim/finki/develop/finkwave/service/AuthService.java
rb70fbeb r3238007 1 1 package com.ukim.finki.develop.finkwave.service; 2 3 import java.io.IOException; 4 import java.nio.file.Files; 5 import java.nio.file.Path; 6 import java.nio.file.Paths; 7 import java.util.UUID; 2 8 3 9 import org.springframework.security.core.Authentication; … … 5 11 import org.springframework.security.crypto.password.PasswordEncoder; 6 12 import org.springframework.stereotype.Service; 13 import org.springframework.web.multipart.MultipartFile; 7 14 8 15 import com.ukim.finki.develop.finkwave.config.AuthProperties; 9 import com.ukim.finki.develop.finkwave.model.dto.AuthRequestDto; 10 import com.ukim.finki.develop.finkwave.model.dto.LoginRequestDto; 11 import com.ukim.finki.develop.finkwave.model.dto.UserResponseDto; 16 import com.ukim.finki.develop.finkwave.exceptions.InvalidCredentialsException; 17 import com.ukim.finki.develop.finkwave.exceptions.InvalidFileException; 18 import com.ukim.finki.develop.finkwave.exceptions.UnauthenticatedException; 19 import com.ukim.finki.develop.finkwave.exceptions.UserAlreadyExistsException; 20 import com.ukim.finki.develop.finkwave.exceptions.UserNotFoundException; 12 21 import com.ukim.finki.develop.finkwave.model.NonAdminUser; 13 22 import com.ukim.finki.develop.finkwave.model.RefreshToken; 14 23 import com.ukim.finki.develop.finkwave.model.Role; 15 24 import com.ukim.finki.develop.finkwave.model.User; 25 import com.ukim.finki.develop.finkwave.model.dto.AuthRequestDto; 26 import com.ukim.finki.develop.finkwave.model.dto.LoginRequestDto; 27 import com.ukim.finki.develop.finkwave.model.dto.UserResponseDto; 16 28 import com.ukim.finki.develop.finkwave.repository.NonAdminUserRepository; 17 29 import com.ukim.finki.develop.finkwave.repository.UserRepository; … … 21 33 import jakarta.transaction.Transactional; 22 34 import lombok.RequiredArgsConstructor; 23 import org.springframework.web.multipart.MultipartFile;24 25 import java.io.IOException;26 import java.nio.file.Files;27 import java.nio.file.Path;28 import java.nio.file.Paths;29 import java.util.UUID;30 35 31 36 @Service … … 39 44 private final AuthProperties authProperties; 40 45 46 private static final long MAX_FILE_SIZE = 2_000_000; 41 47 42 48 @Transactional … … 44 50 throws IOException { 45 51 if (userRepository.findByUsername(authRequestDto.username()).isPresent()){ 46 throw new RuntimeException("Error creating user.");52 throw new UserAlreadyExistsException(); 47 53 } 48 54 User user = createNonAdminUser(authRequestDto); … … 52 58 public UserResponseDto login(HttpServletResponse response, LoginRequestDto loginRequestDto){ 53 59 User user = userRepository.findByUsername(loginRequestDto.username()) 54 .orElseThrow( () -> new RuntimeException("Invalid credentials."));60 .orElseThrow(InvalidCredentialsException::new); 55 61 56 62 if (!passwordEncoder.matches(loginRequestDto.password(), user.getPassword())){ 57 throw new RuntimeException("Invalid credentials.");63 throw new InvalidCredentialsException(); 58 64 } 59 65 … … 74 80 public UserResponseDto getUserDtoByUsername(String username){ 75 81 User user = userRepository.findByUsername(username) 76 .orElseThrow( () -> new RuntimeException("Invalid credentials."));82 .orElseThrow(UserNotFoundException::new); 77 83 78 84 return userResponseFromUser(user); … … 103 109 Authentication authentication= SecurityContextHolder.getContext().getAuthentication(); 104 110 if (authentication == null || !authentication.isAuthenticated()) { 105 throw new RuntimeException("User not authenticated.");111 throw new UnauthenticatedException(); 106 112 } 107 113 108 114 String username=authentication.getName(); 109 115 110 111 116 return userRepository.findByUsername(username).map(User::getId) 112 .orElseThrow( ()->new RuntimeException("User not found."));117 .orElseThrow(UserNotFoundException::new); 113 118 } 114 119 … … 124 129 125 130 MultipartFile profilePhoto = authRequestDto.profilePhoto(); 126 if (profilePhoto != null) { 127 if (profilePhoto.getContentType() != null && !profilePhoto.getContentType().startsWith("image/")) 128 throw new IllegalArgumentException("Invalid fyle type."); 131 if (profilePhoto != null && !profilePhoto.isEmpty()) { 132 String contentType = profilePhoto.getContentType(); 133 if (contentType == null || !contentType.startsWith("image/")) { 134 throw InvalidFileException.invalidType(); 135 } 129 136 130 if (profilePhoto.getSize() > 2_000_000) {131 throw new IllegalArgumentException(("File too large."));137 if (profilePhoto.getSize() > MAX_FILE_SIZE) { 138 throw InvalidFileException.tooLarge(MAX_FILE_SIZE); 132 139 } 133 140 -
finkwave/src/main/java/com/ukim/finki/develop/finkwave/service/RefreshTokenService.java
rb70fbeb r3238007 1 1 package com.ukim.finki.develop.finkwave.service; 2 3 import com.ukim.finki.develop.finkwave.config.AuthProperties;4 import com.ukim.finki.develop.finkwave.model.RefreshToken;5 import com.ukim.finki.develop.finkwave.model.User;6 import com.ukim.finki.develop.finkwave.repository.RefreshTokenRepository;7 import lombok.RequiredArgsConstructor;8 import org.springframework.stereotype.Service;9 2 10 3 import java.time.Instant; … … 12 5 import java.util.Optional; 13 6 import java.util.UUID; 7 8 import org.springframework.stereotype.Service; 9 10 import com.ukim.finki.develop.finkwave.config.AuthProperties; 11 import com.ukim.finki.develop.finkwave.exceptions.InvalidTokenException; 12 import com.ukim.finki.develop.finkwave.model.RefreshToken; 13 import com.ukim.finki.develop.finkwave.model.User; 14 import com.ukim.finki.develop.finkwave.repository.RefreshTokenRepository; 15 16 import lombok.RequiredArgsConstructor; 14 17 15 18 @Service … … 32 35 33 36 public RefreshToken validateRefreshToken(String token){ 34 RefreshToken refreshToken = findByToken(token).orElseThrow(() -> new RuntimeException("Invalid token")); 35 if (refreshToken.isRevoked() || refreshToken.getExpiresAt().isBefore(Instant.now())){ 36 throw new RuntimeException("Invalid refresh token"); 37 RefreshToken refreshToken = findByToken(token) 38 .orElseThrow(() -> new InvalidTokenException("Invalid refresh token.")); 39 if (refreshToken.isRevoked()){ 40 throw new InvalidTokenException("Refresh token has been revoked."); 41 } 42 if (refreshToken.getExpiresAt().isBefore(Instant.now())){ 43 throw new InvalidTokenException("Refresh token has expired."); 37 44 } 38 45 return refreshToken; -
frontend/src/pages/Login.tsx
rb70fbeb r3238007 28 28 error.response?.data?.error || 29 29 "Login failed. Please check your credentials."; 30 setError(errorMessage); 31 toast.error(errorMessage); 30 setError(`Login failed: ${errorMessage}`); 32 31 } 33 32 }; -
frontend/src/pages/Register.tsx
rb70fbeb r3238007 58 58 const errorMessage = 59 59 error.response?.data?.error || "Registration failed. Please try again."; 60 setError(errorMessage); 61 toast.error(errorMessage); 60 setError(`Registration failed: ${errorMessage}`); 62 61 } 63 62 };
Note:
See TracChangeset
for help on using the changeset viewer.
