Security implementation

This commit is contained in:
harish
2024-08-21 18:21:20 +05:30
parent 324490da69
commit 7a080504aa
30 changed files with 721 additions and 78 deletions

View File

@@ -6,9 +6,11 @@ import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.ExampleObject;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import jakarta.validation.Valid;
import net.gepafin.tendermanagement.model.request.LoginReq;
import net.gepafin.tendermanagement.model.request.UpdateUserReq;
import net.gepafin.tendermanagement.model.request.UserReq;
import net.gepafin.tendermanagement.model.response.UserResponseBean;
import net.gepafin.tendermanagement.model.util.JWTToken;
import net.gepafin.tendermanagement.model.util.Response;
import net.gepafin.tendermanagement.web.rest.api.errors.ErrorConstants;
import org.springframework.http.HttpStatus;
@@ -28,13 +30,13 @@ public interface UserApi {
responses = {
@ApiResponse(responseCode = "200", description = "OK"),
@ApiResponse(responseCode = "404", description = "Not Found", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = {
@ExampleObject(value = ErrorConstants.NOTFOUND_ERROR_EXAMPLE) })),
@ExampleObject(value = ErrorConstants.NOTFOUND_ERROR_EXAMPLE)})),
@ApiResponse(responseCode = "401", description = "Unauthorized", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = {
@ExampleObject(value = ErrorConstants.UNAUTHORIZED_ERROR_EXAMPLE) })),
@ExampleObject(value = ErrorConstants.UNAUTHORIZED_ERROR_EXAMPLE)})),
@ApiResponse(responseCode = "400", description = "Bad Request", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = {
@ExampleObject(value = ErrorConstants.BADREQUEST_ERROR_EXAMPLE) })) })
@ExampleObject(value = ErrorConstants.BADREQUEST_ERROR_EXAMPLE)}))})
@RequestMapping(value = "",
produces = { "application/json" },
produces = {"application/json"},
method = RequestMethod.POST)
default ResponseEntity<Response<UserResponseBean>> createUser(
@Parameter(description = "User request object", required = true) @Valid @RequestBody UserReq userReq) {
@@ -45,13 +47,13 @@ public interface UserApi {
responses = {
@ApiResponse(responseCode = "200", description = "OK"),
@ApiResponse(responseCode = "404", description = "Not Found", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = {
@ExampleObject(value = ErrorConstants.NOTFOUND_ERROR_EXAMPLE) })),
@ExampleObject(value = ErrorConstants.NOTFOUND_ERROR_EXAMPLE)})),
@ApiResponse(responseCode = "401", description = "Unauthorized", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = {
@ExampleObject(value = ErrorConstants.UNAUTHORIZED_ERROR_EXAMPLE) })),
@ExampleObject(value = ErrorConstants.UNAUTHORIZED_ERROR_EXAMPLE)})),
@ApiResponse(responseCode = "400", description = "Bad Request", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = {
@ExampleObject(value = ErrorConstants.BADREQUEST_ERROR_EXAMPLE) })) })
@ExampleObject(value = ErrorConstants.BADREQUEST_ERROR_EXAMPLE)}))})
@RequestMapping(value = "/{userId}",
produces = { "application/json" },
produces = {"application/json"},
method = RequestMethod.PUT)
default ResponseEntity<Response<UserResponseBean>> updateUser(
@Parameter(description = "The user id", required = true) @PathVariable("userId") Long userId,
@@ -63,13 +65,13 @@ public interface UserApi {
responses = {
@ApiResponse(responseCode = "200", description = "OK"),
@ApiResponse(responseCode = "404", description = "Not Found", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = {
@ExampleObject(value = ErrorConstants.NOTFOUND_ERROR_EXAMPLE) })),
@ExampleObject(value = ErrorConstants.NOTFOUND_ERROR_EXAMPLE)})),
@ApiResponse(responseCode = "401", description = "Unauthorized", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = {
@ExampleObject(value = ErrorConstants.UNAUTHORIZED_ERROR_EXAMPLE) })),
@ExampleObject(value = ErrorConstants.UNAUTHORIZED_ERROR_EXAMPLE)})),
@ApiResponse(responseCode = "400", description = "Bad Request", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = {
@ExampleObject(value = ErrorConstants.BADREQUEST_ERROR_EXAMPLE) })) })
@ExampleObject(value = ErrorConstants.BADREQUEST_ERROR_EXAMPLE)}))})
@RequestMapping(value = "/{userId}",
produces = { "application/json" },
produces = {"application/json"},
method = RequestMethod.GET)
default ResponseEntity<Response<UserResponseBean>> getUserById(
@Parameter(description = "The user id", required = true) @PathVariable("userId") Long userId) {
@@ -80,15 +82,26 @@ public interface UserApi {
responses = {
@ApiResponse(responseCode = "200", description = "OK"),
@ApiResponse(responseCode = "404", description = "Not Found", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = {
@ExampleObject(value = ErrorConstants.NOTFOUND_ERROR_EXAMPLE) })),
@ExampleObject(value = ErrorConstants.NOTFOUND_ERROR_EXAMPLE)})),
@ApiResponse(responseCode = "401", description = "Unauthorized", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = {
@ExampleObject(value = ErrorConstants.UNAUTHORIZED_ERROR_EXAMPLE) })),
@ExampleObject(value = ErrorConstants.UNAUTHORIZED_ERROR_EXAMPLE)})),
@ApiResponse(responseCode = "400", description = "Bad Request", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = {
@ExampleObject(value = ErrorConstants.BADREQUEST_ERROR_EXAMPLE) })) })
@ExampleObject(value = ErrorConstants.BADREQUEST_ERROR_EXAMPLE)}))})
@RequestMapping(value = "/{userId}",
method = RequestMethod.DELETE)
default ResponseEntity<Response<Void>> deleteUser(
@Parameter(description = "The user id", required = true) @PathVariable("userId") Long userId) {
return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED);
}
@Operation(summary = "Api to login user",
responses = {
@ApiResponse(responseCode = "200", description = "OK"),
@ApiResponse(responseCode = "400", description = "Bad Request"),
@ApiResponse(responseCode = "401", description = "Unauthorized")})
@RequestMapping(value = "/login",
produces = {"application/json"},
method = RequestMethod.POST)
ResponseEntity<Response<JWTToken>> login(
@Parameter(description = "Login request object", required = true) @Valid @RequestBody LoginReq loginReq);
}

View File

@@ -0,0 +1,23 @@
package net.gepafin.tendermanagement.web.rest.api.errors;
import net.gepafin.tendermanagement.model.util.Response;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.http.ResponseEntity;
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(CustomValidationException.class)
public ResponseEntity<Response<Void>> handleCustomValidationException(CustomValidationException ex) {
return ResponseEntity.status(HttpStatus.BAD_REQUEST)
.body(new Response<>(null, ex.getStatus(), ex.getMessage()));
}
@ExceptionHandler(ResourceNotFoundException.class)
public ResponseEntity<Response<Void>> handleResourceNotFoundException(ResourceNotFoundException ex) {
return ResponseEntity.status(HttpStatus.NOT_FOUND)
.body(new Response<>(null, ex.getStatus(), ex.getMessage()));
}
}

View File

@@ -0,0 +1,55 @@
package net.gepafin.tendermanagement.web.rest.api.impl;
import net.gepafin.tendermanagement.entities.RoleEntity;
import net.gepafin.tendermanagement.entities.UserEntity;
import net.gepafin.tendermanagement.repositories.RoleRepository;
import net.gepafin.tendermanagement.repositories.UserRepository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Collections;
@Service
public class CustomUserDetailsService implements UserDetailsService {
private final Logger log = LoggerFactory.getLogger(CustomUserDetailsService.class);
private final UserRepository userRepository;
private final RoleRepository roleRepository;
public CustomUserDetailsService(UserRepository userRepository, RoleRepository roleRepository) {
this.userRepository = userRepository;
this.roleRepository = roleRepository;
}
@Override
@Transactional
public UserDetails loadUserByUsername(final String email) throws UsernameNotFoundException {
log.debug("Authenticating {}", email);
UserEntity user = userRepository.findByEmail(email);
if (user == null) {
throw new UsernameNotFoundException("User " + email + " was not found in the database");
}
return createSpringSecurityUser(user);
}
private org.springframework.security.core.userdetails.User createSpringSecurityUser(UserEntity user) {
RoleEntity role = user.getRoleEntity();
GrantedAuthority grantedAuthority = new SimpleGrantedAuthority(role.getRoleName());
return new org.springframework.security.core.userdetails.User(
user.getEmail(),
user.getPassword(),
Collections.singletonList(grantedAuthority)
);
}
}

View File

@@ -3,14 +3,16 @@ package net.gepafin.tendermanagement.web.rest.api.impl;
import jakarta.validation.Valid;
import net.gepafin.tendermanagement.config.Translator;
import net.gepafin.tendermanagement.constants.GepafinConstant;
import net.gepafin.tendermanagement.model.request.LoginReq;
import net.gepafin.tendermanagement.model.request.UpdateUserReq;
import net.gepafin.tendermanagement.model.request.UserReq;
import net.gepafin.tendermanagement.model.response.UserResponseBean;
import net.gepafin.tendermanagement.model.util.JWTToken;
import net.gepafin.tendermanagement.model.util.Response;
import net.gepafin.tendermanagement.service.UserService;
import net.gepafin.tendermanagement.web.rest.api.UserApi;
import net.gepafin.tendermanagement.web.rest.api.errors.Status;
import net.gepafin.tendermanagement.web.rest.api.errors.Status;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
@@ -21,6 +23,7 @@ import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("${openapi.gepafin.base-path:/v1/user}")
@Validated
public class UserApiController implements UserApi {
private final Logger log = LoggerFactory.getLogger(UserApiController.class);
@@ -31,42 +34,45 @@ public class UserApiController implements UserApi {
@Override
public ResponseEntity<Response<UserResponseBean>> createUser(
@Valid @RequestBody UserReq userReq) {
log.info("Create User with - Request Body: {}", userReq);
UserResponseBean createdUser = userService.createUser(userReq);
return ResponseEntity.status(HttpStatus.CREATED)
.body(new Response<>(createdUser, Status.SUCCESS, Translator.toLocale(GepafinConstant.USER_CREATED_SUCCESS_MSG)));
log.info("Create User with - Request Body: {}", userReq);
UserResponseBean createdUser = userService.createUser(userReq);
return ResponseEntity.status(HttpStatus.CREATED)
.body(new Response<>(createdUser, Status.SUCCESS, Translator.toLocale(GepafinConstant.USER_CREATED_SUCCESS_MSG)));
}
@Override
public ResponseEntity<Response<UserResponseBean>> updateUser(
@PathVariable("userId") Long userId,
@Valid @RequestBody UpdateUserReq userReq) {
log.info("Update User - User ID: {}, Request Body: {}", userId, userReq);
UserResponseBean updatedUser = userService.updateUser(userId, userReq);
return ResponseEntity.status(HttpStatus.OK)
.body(new Response<>(updatedUser, Status.SUCCESS, Translator.toLocale(GepafinConstant.USER_UPDATED_SUCCESS_MSG)));
log.info("Update User - User ID: {}, Request Body: {}", userId, userReq);
UserResponseBean updatedUser = userService.updateUser(userId, userReq);
return ResponseEntity.status(HttpStatus.OK)
.body(new Response<>(updatedUser, Status.SUCCESS, Translator.toLocale(GepafinConstant.USER_UPDATED_SUCCESS_MSG)));
}
@Override
public ResponseEntity<Response<UserResponseBean>> getUserById(
@PathVariable("userId") Long userId) {
log.info("Get User by ID - User ID: {}", userId);
UserResponseBean user = userService.getUserById(userId);
return ResponseEntity.status(HttpStatus.OK)
.body(new Response<>(user, Status.SUCCESS, Translator.toLocale(GepafinConstant.GET_USER_SUCCESS_MSG)));
log.info("Get User by ID - User ID: {}", userId);
UserResponseBean user = userService.getUserById(userId);
return ResponseEntity.status(HttpStatus.OK)
.body(new Response<>(user, Status.SUCCESS, Translator.toLocale(GepafinConstant.GET_USER_SUCCESS_MSG)));
}
@Override
public ResponseEntity<Response<Void>> deleteUser(
@PathVariable("userId") Long userId) {
log.info("Delete User By- User ID: {}", userId);
userService.deleteUser(userId);
return ResponseEntity.status(HttpStatus.OK)
.body(new Response<>(null, Status.SUCCESS, Translator.toLocale(GepafinConstant.USER_DELETED_SUCCESS_MSG)));
log.info("Delete User - User ID: {}", userId);
userService.deleteUser(userId);
return ResponseEntity.status(HttpStatus.OK)
.body(new Response<>(null, Status.SUCCESS, Translator.toLocale(GepafinConstant.USER_DELETED_SUCCESS_MSG)));
}
@Override
public ResponseEntity<Response<JWTToken>> login(
@Valid @RequestBody LoginReq loginReq) {
log.info("User login attempt ");
JWTToken jwtToken = userService.login(loginReq);
return ResponseEntity.ok(new Response<>(jwtToken, Status.SUCCESS, Translator.toLocale(GepafinConstant.LOGIN_SUCCESS_MSG)));
}
}