diff --git a/src/main/java/com/pecacm/backend/controllers/UserController.java b/src/main/java/com/pecacm/backend/controllers/UserController.java index 1509fac..82f8e8c 100644 --- a/src/main/java/com/pecacm/backend/controllers/UserController.java +++ b/src/main/java/com/pecacm/backend/controllers/UserController.java @@ -17,6 +17,8 @@ import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.BadCredentialsException; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.web.bind.annotation.*; @@ -55,6 +57,14 @@ public ResponseEntity registerUser(@RequestBody User use return ResponseEntity.status(HttpStatus.CREATED).body(new AuthenticationResponse(jwtToken, newUser)); } + @GetMapping + @PreAuthorize(Constants.HAS_ROLE_MEMBER_AND_ABOVE) + public ResponseEntity getUserInfo() { + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + String email = (String) authentication.getPrincipal(); + return ResponseEntity.ok(userService.getUserByEmail(email)); + } + @PostMapping("/login") @PreAuthorize(Constants.HAS_ANY_ROLE) public ResponseEntity loginUser(@RequestBody AuthenticationRequest request) { diff --git a/src/main/java/com/pecacm/backend/services/EmailService.java b/src/main/java/com/pecacm/backend/services/EmailService.java index e4c7ac7..0f92722 100644 --- a/src/main/java/com/pecacm/backend/services/EmailService.java +++ b/src/main/java/com/pecacm/backend/services/EmailService.java @@ -34,7 +34,7 @@ public void sendVerificationEmail(User user) { mailMessage.setTo(user.getEmail()); mailMessage.setSubject("Email verification"); mailMessage.setText( - "Click on the link to verify your email: " + hostname + "v1/user/verify?token=" + token.getToken() + "Click on the link to verify your email: " + hostname + "verify?token=" + token.getToken() ); javaMailSender.send(mailMessage); } diff --git a/src/main/java/com/pecacm/backend/services/JwtService.java b/src/main/java/com/pecacm/backend/services/JwtService.java index 5947140..01c98c8 100644 --- a/src/main/java/com/pecacm/backend/services/JwtService.java +++ b/src/main/java/com/pecacm/backend/services/JwtService.java @@ -1,9 +1,11 @@ package com.pecacm.backend.services; +import com.pecacm.backend.exception.AcmException; import io.jsonwebtoken.Claims; import io.jsonwebtoken.Jwts; import io.jsonwebtoken.SignatureAlgorithm; import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.HttpStatus; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.stereotype.Service; @@ -28,28 +30,52 @@ public String generateToken(UserDetails userDetails) { } public boolean validateToken(String token, UserDetails userDetails) { - return extractUsername(token).equals(userDetails.getUsername()) && !isTokenExpired(token); + try { + return extractUsername(token).equals(userDetails.getUsername()) && !isTokenExpired(token); + } catch (Exception ex) { + throw new AcmException("Token is invalid", HttpStatus.BAD_REQUEST); + } } public boolean isTokenExpired(String token) { - return extractExpiration(token).before(new Date()); + try { + return extractExpiration(token).before(new Date()); + } catch (Exception ex) { + throw new AcmException("Token is invalid", HttpStatus.BAD_REQUEST); + } } public Date extractExpiration(String token) { - return extractClaim(token, Claims::getExpiration); + try { + return extractClaim(token, Claims::getExpiration); + } catch (Exception ex) { + throw new AcmException("Token is invalid", HttpStatus.BAD_REQUEST); + } } public String extractUsername(String token) { - return extractClaim(token, Claims::getSubject); + try { + return extractClaim(token, Claims::getSubject); + } catch (Exception ex) { + throw new AcmException("Token is invalid", HttpStatus.BAD_REQUEST); + } } public T extractClaim(String token, Function claim) { - Claims claims = extractAllClaims(token); - return claim.apply(claims); + try { + Claims claims = extractAllClaims(token); + return claim.apply(claims); + } catch (Exception ex) { + throw new AcmException("Token is invalid", HttpStatus.BAD_REQUEST); + } } private Claims extractAllClaims(String token) { - return Jwts.parser().setSigningKey(secretKey).parseClaimsJws(token).getBody(); + try { + return Jwts.parser().setSigningKey(secretKey).parseClaimsJws(token).getBody(); + } catch (Exception ex) { + throw new AcmException("Token is invalid", HttpStatus.BAD_REQUEST); + } } } diff --git a/src/main/java/com/pecacm/backend/services/UserService.java b/src/main/java/com/pecacm/backend/services/UserService.java index 8975f29..34479f2 100644 --- a/src/main/java/com/pecacm/backend/services/UserService.java +++ b/src/main/java/com/pecacm/backend/services/UserService.java @@ -35,11 +35,11 @@ public UserService(UserRepository userRepository, VerificationTokenRepository ve } public User addUser(User user, PasswordEncoder passwordEncoder) { - if(userRepository.existsByEmailOrSid(user.getEmail(), user.getSid())) { + if (userRepository.existsByEmailOrSid(user.getEmail(), user.getSid())) { throw new AcmException("User with given email or SID already exists", HttpStatus.BAD_REQUEST); } - if(Strings.isBlank(user.getEmail()) || Strings.isBlank(user.getPassword()) || user.getSid() == null || - Strings.isBlank(user.getBranch()) + if (Strings.isBlank(user.getEmail()) || Strings.isBlank(user.getPassword()) || user.getSid() == null || + Strings.isBlank(user.getBranch()) ) { throw new AcmException("One or more required fields are empty", HttpStatus.BAD_REQUEST); } @@ -56,7 +56,7 @@ public User loadUserByUsername(String email) { public User verifyUser(UUID tokenId) { VerificationToken token = verificationTokenRepository.findById(tokenId).orElseThrow(() -> - new AcmException("Verification token not found", HttpStatus.NOT_FOUND) + new AcmException("Verification token not found", HttpStatus.NOT_FOUND) ); // TODO: check token expiration User user = token.getUser(); @@ -69,9 +69,9 @@ public User verifyUser(UUID tokenId) { public String changeRole(AssignRoleRequest assignRoleRequest) { String userEmail = SecurityContextHolder.getContext().getAuthentication().getPrincipal().toString(); Role requesterRole = userRepository.findRoleByEmail(userEmail) - .orElseThrow(() -> - new AcmException(ErrorConstants.USER_NOT_FOUND, HttpStatus.NOT_FOUND) - ); + .orElseThrow(() -> + new AcmException(ErrorConstants.USER_NOT_FOUND, HttpStatus.NOT_FOUND) + ); Role requestUserRole = userRepository.findRoleByEmail(assignRoleRequest.getEmail()) .orElseThrow(() -> @@ -82,8 +82,7 @@ public String changeRole(AssignRoleRequest assignRoleRequest) { Boolean isUserAuthorizedToChangeRole = requesterRole.equals(Role.Core) || requesterRole.equals(Role.Admin); Boolean isRequestUserRoleLessThanRequester = requestUserRole.compareTo(requesterRole) < 0; - if (isNewRoleLessThanUserRole && isUserAuthorizedToChangeRole && isRequestUserRoleLessThanRequester) - { + if (isNewRoleLessThanUserRole && isUserAuthorizedToChangeRole && isRequestUserRoleLessThanRequester) { userRepository.updateRoleByEmail(assignRoleRequest.getEmail(), assignRoleRequest.getNewRole()); return Constants.UPDATE_SUCCESS; } @@ -91,13 +90,20 @@ public String changeRole(AssignRoleRequest assignRoleRequest) { throw new AcmException(ErrorConstants.USER_UNAUTHORIZED, HttpStatus.UNAUTHORIZED); } - public User getUserById(Integer userId){ + public User getUserById(Integer userId) { return userRepository.findById(userId) .orElseThrow(() -> new AcmException(ErrorConstants.USER_NOT_FOUND, HttpStatus.NOT_FOUND) ); } + public User getUserByEmail(String email) { + return userRepository.findByEmail(email) + .orElseThrow(() -> + new AcmException(ErrorConstants.USER_NOT_FOUND, HttpStatus.NOT_FOUND) + ); + } + public Long getRank(Integer score) { return userRepository.countByXpGreaterThan(score) + 1; } diff --git a/src/main/resources/application-local.yml b/src/main/resources/application-local.yml index cef25b4..1510494 100644 --- a/src/main/resources/application-local.yml +++ b/src/main/resources/application-local.yml @@ -1,3 +1,5 @@ +server: + port: 8080 spring: datasource: url: jdbc:postgresql://localhost:5432/acm @@ -23,4 +25,7 @@ spring: smtp: auth: true starttls: - enable: true \ No newline at end of file + enable: true +verify: + base: + frontend: http://localhost:3000/ \ No newline at end of file diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 362ccbe..a9d735d 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -51,4 +51,4 @@ jwt: secret: nyanpasu verify: base: - frontend: http://localhost:8080/ \ No newline at end of file + frontend: https://pecacm.vercel.app/ \ No newline at end of file