Commit 7a114ddc authored by Phùng Quốc Toàn's avatar Phùng Quốc Toàn

feat: add exception for unauthenticate api

parent 2b4e8dad
...@@ -53,16 +53,19 @@ ...@@ -53,16 +53,19 @@
<artifactId>mapstruct</artifactId> <artifactId>mapstruct</artifactId>
<version>${mapstruct.version}</version> <version>${mapstruct.version}</version>
</dependency> </dependency>
<dependency>
<groupId>com.nimbusds</groupId>
<artifactId>nimbus-jose-jwt</artifactId>
<version>9.30.1</version>
</dependency>
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId> <artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-resource-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
</dependencies> </dependencies>
<build> <build>
......
package com.devteria.identityservice.configuration;
import com.devteria.identityservice.entity.User;
import com.devteria.identityservice.enums.Role;
import com.devteria.identityservice.repository.UserRepository;
import lombok.AccessLevel;
import lombok.RequiredArgsConstructor;
import lombok.experimental.FieldDefaults;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.ApplicationRunner;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.crypto.password.PasswordEncoder;
import java.util.HashSet;
@Configuration
@RequiredArgsConstructor
@FieldDefaults(level = AccessLevel.PRIVATE, makeFinal = true)
@Slf4j
public class ApplicationInitConfig {
PasswordEncoder passwordEncoder;
@Bean
ApplicationRunner runner(UserRepository userRepository) {
return args -> {
if (!userRepository.existsByUsername("admin")) {
var roles = new HashSet<String>();
roles.add(Role.ADMIN.name());
User user = User.builder()
.username("admin")
.password(passwordEncoder.encode("admin"))
.roles(roles)
.build();
userRepository.save(user);
log.warn("Admin user created with username: admin and password: admin");
}
};
}
}
package com.devteria.identityservice.configuration;
import com.devteria.identityservice.dto.request.ApiResponse;
import com.devteria.identityservice.exception.ErrorCode;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint;
import java.io.IOException;
public class JwtAuthenticationEntryPoint implements AuthenticationEntryPoint {
@Override
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException {
ErrorCode errorCode = ErrorCode.UNAUTHENTICATED;
response.setStatus(errorCode.getStatusCode().value());
response.setContentType("application/json");
ApiResponse<?> apiResponse = ApiResponse.builder()
.code(errorCode.getCode())
.message(errorCode.getMessage())
.build();
ObjectMapper objectMapper = new ObjectMapper();
response.getWriter().write(objectMapper.writeValueAsString(apiResponse));
response.flushBuffer();
}
}
package com.devteria.identityservice.configuration;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
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.configuration.EnableWebSecurity;
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.oauth2.jose.jws.MacAlgorithm;
import org.springframework.security.oauth2.jwt.JwtDecoder;
import org.springframework.security.oauth2.jwt.NimbusJwtDecoder;
import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationConverter;
import org.springframework.security.oauth2.server.resource.authentication.JwtGrantedAuthoritiesConverter;
import org.springframework.security.web.SecurityFilterChain;
import javax.crypto.spec.SecretKeySpec;
@Configuration
@EnableWebSecurity
@EnableMethodSecurity
public class SecurityConfig {
private final String[] PUBLIC_ENDPOINTS = new String[]{"/auth/token", "/auth/introspect", "/users"};
@Value("${jwt.signerKey}")
private String signerKey;
@Bean
public SecurityFilterChain filterChain(HttpSecurity httpSecurity) throws Exception {
httpSecurity.authorizeHttpRequests(request -> request.requestMatchers(HttpMethod.POST, PUBLIC_ENDPOINTS)
.permitAll()
.anyRequest()
.authenticated());
httpSecurity.oauth2ResourceServer(oauth2 ->
oauth2.jwt(jwtConfigurer ->
jwtConfigurer.decoder(jwtDecoder())
.jwtAuthenticationConverter(jwtConverter()))
.authenticationEntryPoint(new JwtAuthenticationEntryPoint()));
httpSecurity.csrf(AbstractHttpConfigurer::disable);
return httpSecurity.build();
}
@Bean
JwtAuthenticationConverter jwtConverter() {
JwtGrantedAuthoritiesConverter jwtGrantedAuthoritiesConverter = new JwtGrantedAuthoritiesConverter();
jwtGrantedAuthoritiesConverter.setAuthorityPrefix("ROLE_");
JwtAuthenticationConverter jwtAuthenticationConverter = new JwtAuthenticationConverter();
jwtAuthenticationConverter.setJwtGrantedAuthoritiesConverter(jwtGrantedAuthoritiesConverter);
return jwtAuthenticationConverter;
}
@Bean
JwtDecoder jwtDecoder() {
SecretKeySpec secretKeySpec = new SecretKeySpec(signerKey.getBytes(), "HS512");
return NimbusJwtDecoder.withSecretKey(secretKeySpec).macAlgorithm(MacAlgorithm.HS512).build();
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder(10);
}
}
\ No newline at end of file
...@@ -9,6 +9,8 @@ import jakarta.validation.Valid; ...@@ -9,6 +9,8 @@ import jakarta.validation.Valid;
import lombok.AccessLevel; import lombok.AccessLevel;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.experimental.FieldDefaults; import lombok.experimental.FieldDefaults;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import java.util.List; import java.util.List;
...@@ -17,42 +19,56 @@ import java.util.List; ...@@ -17,42 +19,56 @@ import java.util.List;
@RequestMapping("/users") @RequestMapping("/users")
@RequiredArgsConstructor @RequiredArgsConstructor
@FieldDefaults(level = AccessLevel.PRIVATE, makeFinal = true) @FieldDefaults(level = AccessLevel.PRIVATE, makeFinal = true)
@Slf4j
public class UserController { public class UserController {
UserService userService; UserService userService;
@PostMapping @PostMapping
ApiResponse<UserResponse> createUser(@RequestBody @Valid UserCreationRequest request){ ApiResponse<UserResponse> createUser(@RequestBody @Valid UserCreationRequest request) {
return ApiResponse.<UserResponse>builder() return ApiResponse.<UserResponse>builder()
.result(userService.createUser(request)) .result(userService.createUser(request))
.build(); .build();
} }
@GetMapping @GetMapping
ApiResponse<List<UserResponse>> getUsers(){ ApiResponse<List<UserResponse>> getUsers() {
var authentication = SecurityContextHolder.getContext().getAuthentication();
log.info("User :{}", authentication.getName());
authentication.getAuthorities().forEach(grantedAuthority -> log.info(grantedAuthority.getAuthority()));
return ApiResponse.<List<UserResponse>>builder() return ApiResponse.<List<UserResponse>>builder()
.result(userService.getUsers()) .result(userService.getUsers())
.build(); .build();
} }
@GetMapping("/{userId}") @GetMapping("/{userId}")
ApiResponse<UserResponse> getUser(@PathVariable("userId") String userId){ ApiResponse<UserResponse> getUser(@PathVariable("userId") String userId) {
return ApiResponse.<UserResponse>builder() return ApiResponse.<UserResponse>builder()
.result(userService.getUser(userId)) .result(userService.getUser(userId))
.build(); .build();
} }
@PutMapping("/{userId}") @PutMapping("/{userId}")
ApiResponse<UserResponse> updateUser(@PathVariable String userId, @RequestBody UserUpdateRequest request){ ApiResponse<UserResponse> updateUser(@PathVariable String userId, @RequestBody UserUpdateRequest request) {
return ApiResponse.<UserResponse>builder() return ApiResponse.<UserResponse>builder()
.result(userService.updateUser(userId, request)) .result(userService.updateUser(userId, request))
.build(); .build();
} }
@DeleteMapping("/{userId}") @DeleteMapping("/{userId}")
ApiResponse<String> deleteUser(@PathVariable String userId){ ApiResponse<String> deleteUser(@PathVariable String userId) {
userService.deleteUser(userId); userService.deleteUser(userId);
return ApiResponse.<String>builder() return ApiResponse.<String>builder()
.result("User has been deleted") .result("User has been deleted")
.build(); .build();
} }
@GetMapping("/my-info")
ApiResponse<UserResponse> getMyInfo() {
return ApiResponse.<UserResponse>builder()
.result(userService.getMyInfo())
.build();
}
} }
...@@ -4,6 +4,7 @@ import lombok.*; ...@@ -4,6 +4,7 @@ import lombok.*;
import lombok.experimental.FieldDefaults; import lombok.experimental.FieldDefaults;
import java.time.LocalDate; import java.time.LocalDate;
import java.util.Set;
@Data @Data
@NoArgsConstructor @NoArgsConstructor
...@@ -13,8 +14,9 @@ import java.time.LocalDate; ...@@ -13,8 +14,9 @@ import java.time.LocalDate;
public class UserResponse { public class UserResponse {
String id; String id;
String username; String username;
String password;
String firstName; String firstName;
String lastName; String lastName;
LocalDate dob; LocalDate dob;
Set<String> roles;
} }
...@@ -4,65 +4,28 @@ import jakarta.persistence.Entity; ...@@ -4,65 +4,28 @@ import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue; import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType; import jakarta.persistence.GenerationType;
import jakarta.persistence.Id; import jakarta.persistence.Id;
import lombok.*;
import lombok.experimental.FieldDefaults;
import java.time.LocalDate; import java.time.LocalDate;
import java.util.Set;
@Getter
@Setter
@Builder
@NoArgsConstructor
@AllArgsConstructor
@FieldDefaults(level = AccessLevel.PRIVATE)
@Entity @Entity
public class User { public class User {
@Id @Id
@GeneratedValue(strategy = GenerationType.UUID) @GeneratedValue(strategy = GenerationType.UUID)
private String id; String id;
private String username; String username;
private String password; String password;
private String firstName; String firstName;
private String lastName; String lastName;
private LocalDate dob; LocalDate dob;
Set<String> roles;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
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;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public LocalDate getDob() {
return dob;
}
public void setDob(LocalDate dob) {
this.dob = dob;
}
} }
package com.devteria.identityservice.enums;
public enum Role {
ADMIN,
USER,
}
\ No newline at end of file
package com.devteria.identityservice.exception; package com.devteria.identityservice.exception;
import lombok.Getter;
import org.springframework.http.HttpStatus;
import org.springframework.http.HttpStatusCode;
@Getter
public enum ErrorCode { public enum ErrorCode {
UNCATEGORIZED_EXCEPTION(9999, "Uncategorized error"), UNCATEGORIZED_EXCEPTION(9999, "Uncategorized error", HttpStatus.INTERNAL_SERVER_ERROR),
INVALID_KEY(1001, "Uncategorized error"), INVALID_KEY(1001, "Uncategorized error", HttpStatus.BAD_REQUEST),
USER_EXISTED(1002, "User existed"), USER_EXISTED(1002, "User existed", HttpStatus.BAD_REQUEST),
USERNAME_INVALID(1003, "Username must be at least 3 characters"), USERNAME_INVALID(1003, "Username must be at least 3 characters", HttpStatus.BAD_REQUEST),
INVALID_PASSWORD(1004, "Password must be at least 8 characters"), INVALID_PASSWORD(1004, "Password must be at least 8 characters", HttpStatus.BAD_REQUEST),
USER_NOT_EXISTED(1005, "User not existed"), USER_NOT_EXISTED(1005, "User not existed", HttpStatus.NOT_FOUND),
UNAUTHENTICATED(1006, "Unauthenticated"), UNAUTHENTICATED(1006, "Unauthenticated", HttpStatus.UNAUTHORIZED),
UNAUTHORIZED(1007, "You do not have permission", HttpStatus.FORBIDDEN),
; ;
ErrorCode(int code, String message) {
this.code = code;
this.message = message;
}
private int code; private int code;
private String message; private String message;
private HttpStatusCode statusCode;
public int getCode() { ErrorCode(int code, String message, HttpStatusCode statusCode) {
return code; this.code = code;
this.message = message;
this.statusCode = statusCode;
} }
public String getMessage() {
return message;
}
} }
package com.devteria.identityservice.exception; package com.devteria.identityservice.exception;
import com.devteria.identityservice.dto.request.ApiResponse; import com.devteria.identityservice.dto.request.ApiResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ExceptionHandler;
@ControllerAdvice @ControllerAdvice
@Slf4j
public class GlobalExceptionHandler { public class GlobalExceptionHandler {
@ExceptionHandler(value = Exception.class) @ExceptionHandler(value = Exception.class)
ResponseEntity<ApiResponse> handlingRuntimeException(RuntimeException exception){ ResponseEntity<ApiResponse> handlingRuntimeException(RuntimeException exception) {
log.error("Exception: ", exception);
ApiResponse apiResponse = new ApiResponse(); ApiResponse apiResponse = new ApiResponse();
apiResponse.setCode(ErrorCode.UNCATEGORIZED_EXCEPTION.getCode()); apiResponse.setCode(ErrorCode.UNCATEGORIZED_EXCEPTION.getCode());
...@@ -20,25 +24,25 @@ public class GlobalExceptionHandler { ...@@ -20,25 +24,25 @@ public class GlobalExceptionHandler {
} }
@ExceptionHandler(value = AppException.class) @ExceptionHandler(value = AppException.class)
ResponseEntity<ApiResponse> handlingAppException(AppException exception){ ResponseEntity<ApiResponse> handlingAppException(AppException exception) {
ErrorCode errorCode = exception.getErrorCode(); ErrorCode errorCode = exception.getErrorCode();
ApiResponse apiResponse = new ApiResponse(); ApiResponse apiResponse = new ApiResponse();
apiResponse.setCode(errorCode.getCode()); apiResponse.setCode(errorCode.getCode());
apiResponse.setMessage(errorCode.getMessage()); apiResponse.setMessage(errorCode.getMessage());
return ResponseEntity.badRequest().body(apiResponse); return ResponseEntity.status(errorCode.getStatusCode()).body(apiResponse);
} }
@ExceptionHandler(value = MethodArgumentNotValidException.class) @ExceptionHandler(value = MethodArgumentNotValidException.class)
ResponseEntity<ApiResponse> handlingValidation(MethodArgumentNotValidException exception){ ResponseEntity<ApiResponse> handlingValidation(MethodArgumentNotValidException exception) {
String enumKey = exception.getFieldError().getDefaultMessage(); String enumKey = exception.getFieldError().getDefaultMessage();
ErrorCode errorCode = ErrorCode.INVALID_KEY; ErrorCode errorCode = ErrorCode.INVALID_KEY;
try { try {
errorCode = ErrorCode.valueOf(enumKey); errorCode = ErrorCode.valueOf(enumKey);
} catch (IllegalArgumentException e){ } catch (IllegalArgumentException e) {
} }
...@@ -49,4 +53,11 @@ public class GlobalExceptionHandler { ...@@ -49,4 +53,11 @@ public class GlobalExceptionHandler {
return ResponseEntity.badRequest().body(apiResponse); return ResponseEntity.badRequest().body(apiResponse);
} }
@ExceptionHandler(value = AccessDeniedException.class)
ResponseEntity<ApiResponse> handlingAccessDeniedException(AccessDeniedException exception) {
ErrorCode errorCode = ErrorCode.UNAUTHORIZED;
return ResponseEntity.status(errorCode.getStatusCode()).body(ApiResponse.builder().code(errorCode.getCode()).message(errorCode.getMessage()).build());
}
} }
...@@ -4,6 +4,7 @@ import com.devteria.identityservice.dto.request.AuthenticationRequest; ...@@ -4,6 +4,7 @@ import com.devteria.identityservice.dto.request.AuthenticationRequest;
import com.devteria.identityservice.dto.request.IntrospectRequest; import com.devteria.identityservice.dto.request.IntrospectRequest;
import com.devteria.identityservice.dto.response.AuthenticationResponse; import com.devteria.identityservice.dto.response.AuthenticationResponse;
import com.devteria.identityservice.dto.response.IntrospectResponse; import com.devteria.identityservice.dto.response.IntrospectResponse;
import com.devteria.identityservice.entity.User;
import com.devteria.identityservice.exception.AppException; import com.devteria.identityservice.exception.AppException;
import com.devteria.identityservice.exception.ErrorCode; import com.devteria.identityservice.exception.ErrorCode;
import com.devteria.identityservice.repository.UserRepository; import com.devteria.identityservice.repository.UserRepository;
...@@ -21,11 +22,13 @@ import org.springframework.beans.factory.annotation.Value; ...@@ -21,11 +22,13 @@ import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import java.text.ParseException; import java.text.ParseException;
import java.time.Instant; import java.time.Instant;
import java.time.temporal.ChronoUnit; import java.time.temporal.ChronoUnit;
import java.util.Date; import java.util.Date;
import java.util.StringJoiner;
@Service @Service
@RequiredArgsConstructor @RequiredArgsConstructor
...@@ -55,7 +58,7 @@ public class AuthenticationService { ...@@ -55,7 +58,7 @@ public class AuthenticationService {
.build(); .build();
} }
public AuthenticationResponse authenticate(AuthenticationRequest request){ public AuthenticationResponse authenticate(AuthenticationRequest request) {
PasswordEncoder passwordEncoder = new BCryptPasswordEncoder(10); PasswordEncoder passwordEncoder = new BCryptPasswordEncoder(10);
var user = userRepository.findByUsername(request.getUsername()) var user = userRepository.findByUsername(request.getUsername())
.orElseThrow(() -> new AppException(ErrorCode.USER_NOT_EXISTED)); .orElseThrow(() -> new AppException(ErrorCode.USER_NOT_EXISTED));
...@@ -65,7 +68,7 @@ public class AuthenticationService { ...@@ -65,7 +68,7 @@ public class AuthenticationService {
if (!authenticated) if (!authenticated)
throw new AppException(ErrorCode.UNAUTHENTICATED); throw new AppException(ErrorCode.UNAUTHENTICATED);
var token = generateToken(request.getUsername()); var token = generateToken(user);
return AuthenticationResponse.builder() return AuthenticationResponse.builder()
.token(token) .token(token)
...@@ -73,17 +76,17 @@ public class AuthenticationService { ...@@ -73,17 +76,17 @@ public class AuthenticationService {
.build(); .build();
} }
private String generateToken(String username) { private String generateToken(User user) {
JWSHeader header = new JWSHeader(JWSAlgorithm.HS512); JWSHeader header = new JWSHeader(JWSAlgorithm.HS512);
JWTClaimsSet jwtClaimsSet = new JWTClaimsSet.Builder() JWTClaimsSet jwtClaimsSet = new JWTClaimsSet.Builder()
.subject(username) .subject(user.getUsername())
.issuer("devteria.com") .issuer("demo_jwt")
.issueTime(new Date()) .issueTime(new Date())
.expirationTime(new Date( .expirationTime(new Date(
Instant.now().plus(1, ChronoUnit.HOURS).toEpochMilli() Instant.now().plus(1, ChronoUnit.HOURS).toEpochMilli()
)) ))
.claim("userId", "Custom") .claim("scope", buildScope(user))
.build(); .build();
Payload payload = new Payload(jwtClaimsSet.toJSONObject()); Payload payload = new Payload(jwtClaimsSet.toJSONObject());
...@@ -98,4 +101,14 @@ public class AuthenticationService { ...@@ -98,4 +101,14 @@ public class AuthenticationService {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
} }
private String buildScope(User user) {
StringJoiner stringJoiner = new StringJoiner("");
if (!CollectionUtils.isEmpty(user.getRoles())) {
user.getRoles().forEach(stringJoiner::add);
}
return stringJoiner.toString();
}
} }
...@@ -4,6 +4,7 @@ import com.devteria.identityservice.dto.request.UserCreationRequest; ...@@ -4,6 +4,7 @@ import com.devteria.identityservice.dto.request.UserCreationRequest;
import com.devteria.identityservice.dto.request.UserUpdateRequest; import com.devteria.identityservice.dto.request.UserUpdateRequest;
import com.devteria.identityservice.dto.response.UserResponse; import com.devteria.identityservice.dto.response.UserResponse;
import com.devteria.identityservice.entity.User; import com.devteria.identityservice.entity.User;
import com.devteria.identityservice.enums.Role;
import com.devteria.identityservice.exception.AppException; import com.devteria.identityservice.exception.AppException;
import com.devteria.identityservice.exception.ErrorCode; import com.devteria.identityservice.exception.ErrorCode;
import com.devteria.identityservice.mapper.UserMapper; import com.devteria.identityservice.mapper.UserMapper;
...@@ -11,27 +12,36 @@ import com.devteria.identityservice.repository.UserRepository; ...@@ -11,27 +12,36 @@ import com.devteria.identityservice.repository.UserRepository;
import lombok.AccessLevel; import lombok.AccessLevel;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.experimental.FieldDefaults; import lombok.experimental.FieldDefaults;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import lombok.extern.slf4j.Slf4j;
import org.springframework.security.access.prepost.PostAuthorize;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.util.HashSet;
import java.util.List; import java.util.List;
@Service @Service
@RequiredArgsConstructor @RequiredArgsConstructor
@FieldDefaults(level = AccessLevel.PRIVATE, makeFinal = true) @FieldDefaults(level = AccessLevel.PRIVATE, makeFinal = true)
@Slf4j
public class UserService { public class UserService {
UserRepository userRepository; UserRepository userRepository;
UserMapper userMapper; UserMapper userMapper;
PasswordEncoder passwordEncoder;
public UserResponse createUser(UserCreationRequest request){ public UserResponse createUser(UserCreationRequest request) {
if (userRepository.existsByUsername(request.getUsername())) if (userRepository.existsByUsername(request.getUsername()))
throw new AppException(ErrorCode.USER_EXISTED); throw new AppException(ErrorCode.USER_EXISTED);
User user = userMapper.toUser(request); User user = userMapper.toUser(request);
PasswordEncoder passwordEncoder = new BCryptPasswordEncoder(10);
user.setPassword(passwordEncoder.encode(request.getPassword())); user.setPassword(passwordEncoder.encode(request.getPassword()));
HashSet<String> roles = new HashSet<>();
roles.add(Role.USER.name());
user.setRoles(roles);
return userMapper.toUserResponse(userRepository.save(user)); return userMapper.toUserResponse(userRepository.save(user));
} }
...@@ -44,17 +54,28 @@ public class UserService { ...@@ -44,17 +54,28 @@ public class UserService {
return userMapper.toUserResponse(userRepository.save(user)); return userMapper.toUserResponse(userRepository.save(user));
} }
public void deleteUser(String userId){ public void deleteUser(String userId) {
userRepository.deleteById(userId); userRepository.deleteById(userId);
} }
public List<UserResponse> getUsers(){ @PreAuthorize("hasRole('ADMIN')")
public List<UserResponse> getUsers() {
log.info("Get all users");
return userRepository.findAll().stream() return userRepository.findAll().stream()
.map(userMapper::toUserResponse).toList(); .map(userMapper::toUserResponse).toList();
} }
public UserResponse getUser(String id){ @PostAuthorize("returnObject.username == authentication.name or hasRole('ADMIN')")
public UserResponse getUser(String id) {
log.info("Get user with id: {}", id);
return userMapper.toUserResponse(userRepository.findById(id) return userMapper.toUserResponse(userRepository.findById(id)
.orElseThrow(() -> new RuntimeException("User not found"))); .orElseThrow(() -> new RuntimeException("User not found")));
} }
public UserResponse getMyInfo() {
String name = SecurityContextHolder.getContext().getAuthentication().getName();
User user = userRepository.findByUsername(name).orElseThrow(() -> new AppException(ErrorCode.USER_NOT_EXISTED));
return userMapper.toUserResponse(user);
}
} }
...@@ -5,9 +5,9 @@ server: ...@@ -5,9 +5,9 @@ server:
spring: spring:
datasource: datasource:
url: "jdbc:mysql://localhost:3306/identity_service" url: "jdbc:mysql://10.84.86.33:3306/demo_jwt"
username: root username: rdvivas
password: root password: rdvivas@123
jpa: jpa:
hibernate: hibernate:
ddl-auto: update ddl-auto: update
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment