From abc399860e53f873b2006e7ae7686aafada67ced Mon Sep 17 00:00:00 2001 From: gfxv Date: Wed, 12 Mar 2025 18:57:51 +0300 Subject: [PATCH] feat: add auth controller with payloads --- .../gfxv/blps/controller/AuthController.java | 95 +++++++++++++++++++ .../blps/payload/request/LoginRequest.java | 27 ++++++ .../blps/payload/request/RegisterRequest.java | 36 +++++++ .../blps/payload/response/JwtResponse.java | 54 +++++++++++ 4 files changed, 212 insertions(+) create mode 100644 src/main/java/dev/gfxv/blps/controller/AuthController.java create mode 100644 src/main/java/dev/gfxv/blps/payload/request/LoginRequest.java create mode 100644 src/main/java/dev/gfxv/blps/payload/request/RegisterRequest.java create mode 100644 src/main/java/dev/gfxv/blps/payload/response/JwtResponse.java diff --git a/src/main/java/dev/gfxv/blps/controller/AuthController.java b/src/main/java/dev/gfxv/blps/controller/AuthController.java new file mode 100644 index 0000000..9bdeec8 --- /dev/null +++ b/src/main/java/dev/gfxv/blps/controller/AuthController.java @@ -0,0 +1,95 @@ +package dev.gfxv.blps.controller; + +import dev.gfxv.blps.entity.Role; +import dev.gfxv.blps.entity.User; +import dev.gfxv.blps.payload.request.LoginRequest; +import dev.gfxv.blps.payload.request.RegisterRequest; +import dev.gfxv.blps.payload.response.JwtResponse; +import dev.gfxv.blps.security.JwtUtils; +import dev.gfxv.blps.repository.RoleRepository; +import dev.gfxv.blps.repository.UserRepository; +import dev.gfxv.blps.security.UserDetailsImpl; +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.experimental.FieldDefaults; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.ResponseEntity; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.web.bind.annotation.*; + +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; + +@RestController +@RequestMapping("/api/auth") +@FieldDefaults(level = AccessLevel.PRIVATE, makeFinal = true) +public class AuthController { + + AuthenticationManager authenticationManager; + UserRepository userRepository; + RoleRepository roleRepository; + PasswordEncoder passwordEncoder; + JwtUtils jwtUtils; + + @Autowired + public AuthController( + AuthenticationManager authenticationManager, + UserRepository userRepository, + RoleRepository roleRepository, + PasswordEncoder passwordEncoder, + JwtUtils jwtUtils + ) { + this.authenticationManager = authenticationManager; + this.userRepository = userRepository; + this.roleRepository = roleRepository; + this.passwordEncoder = passwordEncoder; + this.jwtUtils = jwtUtils; + } + + @PostMapping("/register") + public ResponseEntity registerUser(@RequestBody RegisterRequest registerRequest) { + if (userRepository.existsByUsername(registerRequest.getUsername())) { + return ResponseEntity.badRequest().body("Error: Username is already taken!"); + } + + if (userRepository.existsByEmail(registerRequest.getEmail())) { + return ResponseEntity.badRequest().body("Error: Email is already in use!"); + } + + User user = new User(); + user.setUsername(registerRequest.getUsername()); + user.setEmail(registerRequest.getEmail()); + user.setPassword(passwordEncoder.encode(registerRequest.getPassword())); + + Role userRole = roleRepository.findByName("ROLE_USER") + .orElseThrow(() -> new RuntimeException("Error: Role is not found.")); + user.setRoles(Collections.singleton(userRole)); + + userRepository.save(user); + + return ResponseEntity.ok("User registered successfully!"); + } + + @PostMapping("/login") + public ResponseEntity authenticateUser(@RequestBody LoginRequest loginRequest) { + Authentication authentication = authenticationManager.authenticate( + new UsernamePasswordAuthenticationToken(loginRequest.getUsername(), loginRequest.getPassword())); + + SecurityContextHolder.getContext().setAuthentication(authentication); + + String jwt = jwtUtils.generateJwtToken(authentication); + + UserDetailsImpl userDetails = (UserDetailsImpl) authentication.getPrincipal(); + List roles = userDetails.getAuthorities().stream() + .map(GrantedAuthority::getAuthority) + .collect(Collectors.toList()); + + return ResponseEntity.ok(new JwtResponse(jwt, userDetails.getUsername(), roles)); + } +} \ No newline at end of file diff --git a/src/main/java/dev/gfxv/blps/payload/request/LoginRequest.java b/src/main/java/dev/gfxv/blps/payload/request/LoginRequest.java new file mode 100644 index 0000000..96c06d5 --- /dev/null +++ b/src/main/java/dev/gfxv/blps/payload/request/LoginRequest.java @@ -0,0 +1,27 @@ +package dev.gfxv.blps.payload.request; + +import lombok.AccessLevel; +import lombok.Data; +import lombok.experimental.FieldDefaults; + +@FieldDefaults(level = AccessLevel.PRIVATE) +public class LoginRequest { + String username; + String password; + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } +} \ No newline at end of file diff --git a/src/main/java/dev/gfxv/blps/payload/request/RegisterRequest.java b/src/main/java/dev/gfxv/blps/payload/request/RegisterRequest.java new file mode 100644 index 0000000..daafdfb --- /dev/null +++ b/src/main/java/dev/gfxv/blps/payload/request/RegisterRequest.java @@ -0,0 +1,36 @@ +package dev.gfxv.blps.payload.request; + +import lombok.AccessLevel; +import lombok.Data; +import lombok.experimental.FieldDefaults; + +@FieldDefaults(level = AccessLevel.PRIVATE) +public class RegisterRequest { + String username; + String email; + String password; + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } +} diff --git a/src/main/java/dev/gfxv/blps/payload/response/JwtResponse.java b/src/main/java/dev/gfxv/blps/payload/response/JwtResponse.java new file mode 100644 index 0000000..f91e742 --- /dev/null +++ b/src/main/java/dev/gfxv/blps/payload/response/JwtResponse.java @@ -0,0 +1,54 @@ +package dev.gfxv.blps.payload.response; + +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.experimental.FieldDefaults; + +import java.util.List; + +@FieldDefaults(level = AccessLevel.PRIVATE) +public class JwtResponse { + String token; + String type = "Bearer"; + String username; + List roles; + + public JwtResponse(String token, String username, List roles) { + this.token = token; + this.username = username; + this.roles = roles; + } + + public String getToken() { + return token; + } + + public void setToken(String token) { + this.token = token; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public List getRoles() { + return roles; + } + + public void setRoles(List roles) { + this.roles = roles; + } +} \ No newline at end of file