diff --git a/backend/.idea/compiler.xml b/backend/.idea/compiler.xml index 07e72e7..bfc71e1 100644 --- a/backend/.idea/compiler.xml +++ b/backend/.idea/compiler.xml @@ -2,6 +2,7 @@ + diff --git a/backend/src/main/java/com/reactpairdemo/demo/DemoApplication.java b/backend/src/main/java/com/reactpairdemo/demo/DemoApplication.java index 0108661..b6ead96 100644 --- a/backend/src/main/java/com/reactpairdemo/demo/DemoApplication.java +++ b/backend/src/main/java/com/reactpairdemo/demo/DemoApplication.java @@ -1,7 +1,9 @@ package com.reactpairdemo.demo; +import org.modelmapper.ModelMapper; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.Bean; @SpringBootApplication public class DemoApplication { diff --git a/backend/src/main/java/com/reactpairdemo/demo/controller/UserController.java b/backend/src/main/java/com/reactpairdemo/demo/controller/UserController.java new file mode 100644 index 0000000..7bce010 --- /dev/null +++ b/backend/src/main/java/com/reactpairdemo/demo/controller/UserController.java @@ -0,0 +1,44 @@ +package com.reactpairdemo.demo.controller; + +import com.reactpairdemo.demo.dto.UserDto; +import com.reactpairdemo.demo.entity.User; +import com.reactpairdemo.demo.service.UserService; +import jakarta.validation.Valid; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import java.util.List; +import java.util.stream.Collectors; + +@RestController +@RequestMapping("/api/v1/user") +public class UserController { + @Autowired + private UserService userService; + @GetMapping() + public ResponseEntity> getAllUsers() { + + return new ResponseEntity<>(userService.getAllUsers(), HttpStatus.OK); + } + @PostMapping + public ResponseEntity createUser(@Valid @RequestBody UserDto user) { + return new ResponseEntity<>(userService.createUser(user), HttpStatus.CREATED); + } + + @GetMapping("/{id}") + public ResponseEntity getUserById(@PathVariable Long id) { + return new ResponseEntity<>(userService.getUserById(id), HttpStatus.OK); + } + + @PutMapping("/{id}") + public ResponseEntity updateUser(@PathVariable Long id,@Valid @RequestBody UserDto userDto) { + return new ResponseEntity<>(userService.updateUser(id,userDto), HttpStatus.OK); + } + + @DeleteMapping("/{id}") + public ResponseEntity deleteUser(@PathVariable Long id) { + return new ResponseEntity<>(userService.deleteUser(id), HttpStatus.OK); + } +} diff --git a/backend/src/main/java/com/reactpairdemo/demo/dto/UserDto.java b/backend/src/main/java/com/reactpairdemo/demo/dto/UserDto.java new file mode 100644 index 0000000..217e0e8 --- /dev/null +++ b/backend/src/main/java/com/reactpairdemo/demo/dto/UserDto.java @@ -0,0 +1,27 @@ +package com.reactpairdemo.demo.dto; + +import jakarta.persistence.Column; +import jakarta.validation.constraints.Email; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Pattern; +import jakarta.validation.constraints.Size; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +public class UserDto { + private Long id; + @NotNull(message = "Name must not be Null") + @Size(min=4,message = "Enter valid Name") + private String name; + @NotNull(message = "Email must not be Null") + @Email(message = "Invalid Email Format") + private String email; + @NotNull(message = "Password must not be Null") + @Pattern( + regexp = "^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d).{8,}$", + message = "Password must be at least 8 characters long and include at least one uppercase letter, one lowercase letter, and one digit." + ) + private String Password; +} diff --git a/backend/src/main/java/com/reactpairdemo/demo/entity/User.java b/backend/src/main/java/com/reactpairdemo/demo/entity/User.java new file mode 100644 index 0000000..dafea41 --- /dev/null +++ b/backend/src/main/java/com/reactpairdemo/demo/entity/User.java @@ -0,0 +1,19 @@ +package com.reactpairdemo.demo.entity; + +import jakarta.persistence.*; +import lombok.Data; + +@Entity +@Data +public class User { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + @Column(nullable = false) + private String name; + @Column(nullable = false) + private String email; + @Column(nullable = false) + private String Password; + +} diff --git a/backend/src/main/java/com/reactpairdemo/demo/exception/ErrorResponse.java b/backend/src/main/java/com/reactpairdemo/demo/exception/ErrorResponse.java new file mode 100644 index 0000000..b19d46e --- /dev/null +++ b/backend/src/main/java/com/reactpairdemo/demo/exception/ErrorResponse.java @@ -0,0 +1,12 @@ +package com.reactpairdemo.demo.exception; + +import lombok.Builder; +import lombok.Data; + +@Data +@Builder +public class ErrorResponse { + public String message; + public String title; + +} diff --git a/backend/src/main/java/com/reactpairdemo/demo/exception/GlobalExceptionHandler.java b/backend/src/main/java/com/reactpairdemo/demo/exception/GlobalExceptionHandler.java new file mode 100644 index 0000000..2daf45e --- /dev/null +++ b/backend/src/main/java/com/reactpairdemo/demo/exception/GlobalExceptionHandler.java @@ -0,0 +1,53 @@ +package com.reactpairdemo.demo.exception; + +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.validation.FieldError; +import org.springframework.validation.ObjectError; +import org.springframework.web.bind.MethodArgumentNotValidException; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.RestControllerAdvice; +import org.springframework.web.servlet.resource.NoResourceFoundException; + +import java.util.HashMap; +import java.util.Map; + +@RestControllerAdvice +public class GlobalExceptionHandler { + @ExceptionHandler({UserException.class}) + @ResponseBody + public ResponseEntity handleException(Exception e) { + ErrorResponse errorResponse = ErrorResponse.builder().message(e.getMessage()).title(HttpStatus.NOT_FOUND.getReasonPhrase()).build(); + return ResponseEntity.status(HttpStatus.NOT_FOUND).body(errorResponse); + } + + @ExceptionHandler(MethodArgumentNotValidException.class) + @ResponseBody + public ResponseEntity> handleMethodArgumentNotValidException(MethodArgumentNotValidException e) { + Map resp = new HashMap<>(); + e.getBindingResult().getAllErrors().forEach((objectError) ->{ + String fieldName = ((FieldError) objectError).getField(); + String message=objectError.getDefaultMessage(); + + resp.put(fieldName,message); + } ); + + return new ResponseEntity<>(resp, HttpStatus.BAD_REQUEST); + } + + @ExceptionHandler(NoResourceFoundException.class) + @ResponseBody + public ResponseEntity handleNoResourceFoundException(NoResourceFoundException ex) { + + return new ResponseEntity<>(new ErrorResponse(ex.getMessage(), HttpStatus.NOT_FOUND.toString()), HttpStatus.NOT_FOUND); + } + + @ExceptionHandler(IllegalAccessException.class) + @ResponseBody + public ResponseEntity handleIllegalAccessException(IllegalAccessException ex) { + + return new ResponseEntity<>(new ErrorResponse(ex.getMessage(), HttpStatus.BAD_REQUEST.toString()), HttpStatus.NOT_FOUND); + } + +} diff --git a/backend/src/main/java/com/reactpairdemo/demo/exception/UserException.java b/backend/src/main/java/com/reactpairdemo/demo/exception/UserException.java new file mode 100644 index 0000000..e5e5044 --- /dev/null +++ b/backend/src/main/java/com/reactpairdemo/demo/exception/UserException.java @@ -0,0 +1,7 @@ +package com.reactpairdemo.demo.exception; + +public class UserException extends RuntimeException{ + public UserException(String message) { + super(message); + } +} diff --git a/backend/src/main/java/com/reactpairdemo/demo/repository/UserRepository.java b/backend/src/main/java/com/reactpairdemo/demo/repository/UserRepository.java new file mode 100644 index 0000000..535f4e2 --- /dev/null +++ b/backend/src/main/java/com/reactpairdemo/demo/repository/UserRepository.java @@ -0,0 +1,10 @@ +package com.reactpairdemo.demo.repository; + +import com.reactpairdemo.demo.entity.User; +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.Optional; + +public interface UserRepository extends JpaRepository { + Optional findByEmail(String email); +} diff --git a/backend/src/main/java/com/reactpairdemo/demo/service/UserService.java b/backend/src/main/java/com/reactpairdemo/demo/service/UserService.java new file mode 100644 index 0000000..0f50a2b --- /dev/null +++ b/backend/src/main/java/com/reactpairdemo/demo/service/UserService.java @@ -0,0 +1,15 @@ +package com.reactpairdemo.demo.service; + +import com.reactpairdemo.demo.dto.UserDto; + +import java.util.List; + +public interface UserService { + public UserDto createUser(UserDto user); + public UserDto getUserById(Long id); + public UserDto updateUser(Long id,UserDto userDto); + + public String deleteUser(Long id); + + public List getAllUsers(); +} diff --git a/backend/src/main/java/com/reactpairdemo/demo/service/impl/UserServiceImpl.java b/backend/src/main/java/com/reactpairdemo/demo/service/impl/UserServiceImpl.java new file mode 100644 index 0000000..aa5f551 --- /dev/null +++ b/backend/src/main/java/com/reactpairdemo/demo/service/impl/UserServiceImpl.java @@ -0,0 +1,78 @@ +package com.reactpairdemo.demo.service.impl; + +import com.reactpairdemo.demo.dto.UserDto; +import com.reactpairdemo.demo.entity.User; +import com.reactpairdemo.demo.exception.UserException; +import com.reactpairdemo.demo.repository.UserRepository; +import com.reactpairdemo.demo.service.UserService; +import com.reactpairdemo.demo.utils.Mapper; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.Optional; +import java.util.stream.Collectors; + +import static com.reactpairdemo.demo.utils.Constants.DELETE_SUCCESS; +import static com.reactpairdemo.demo.utils.Constants.ID_NOT_FOUND; + +@Service +@Slf4j +public class UserServiceImpl implements UserService { + + private final UserRepository userRepository; + + private final Mapper mapper; + @Autowired + public UserServiceImpl(UserRepository userRepository, Mapper mapper) { + this.userRepository = userRepository; + this.mapper = mapper; + } + + @Override + public UserDto createUser(UserDto user) { + User userResponse=this.mapper.dtoToEntity(user); + User user1=userRepository.save(userResponse); + return mapper.entityToDto(user1); + } + + @Override + public UserDto getUserById(Long id) { + Optional userOptional=userRepository.findById(id); + if(userOptional.isEmpty()){ + throw new UserException(ID_NOT_FOUND); + } + + return mapper.entityToDto(userOptional.get()); + } + + @Override + public UserDto updateUser(Long id, UserDto userDto) { + Optional userOptional=userRepository.findById(id); + if(userOptional.isEmpty()){ + throw new UserException(ID_NOT_FOUND); + } + userOptional.get().setEmail(userDto.getEmail()); + userOptional.get().setName(userDto.getName()); + userOptional.get().setPassword(userDto.getPassword()); + User userResponse=userRepository.save(userOptional.get()); + return mapper.entityToDto(userResponse); + } + + @Override + public String deleteUser(Long id) { + Optional userOptional=userRepository.findById(id); + if(userOptional.isEmpty()){ + throw new UserException(ID_NOT_FOUND); + } + userRepository.deleteById(id); + return DELETE_SUCCESS; + } + + @Override + public List getAllUsers() { + List userList=userRepository.findAll(); + return userList.stream().map(mapper::entityToDto).collect(Collectors.toList()); + } +} diff --git a/backend/src/main/java/com/reactpairdemo/demo/utils/Constants.java b/backend/src/main/java/com/reactpairdemo/demo/utils/Constants.java new file mode 100644 index 0000000..f63f316 --- /dev/null +++ b/backend/src/main/java/com/reactpairdemo/demo/utils/Constants.java @@ -0,0 +1,8 @@ +package com.reactpairdemo.demo.utils; + +public class Constants { + public static String DELETE_SUCCESS ="User Deleted Succesfully"; + public static String ID_NOT_FOUND = "Given Id Not Found !!"; + public static String BASE_URL ="/api/v1/user"; + +} diff --git a/backend/src/main/java/com/reactpairdemo/demo/utils/Mapper.java b/backend/src/main/java/com/reactpairdemo/demo/utils/Mapper.java new file mode 100644 index 0000000..b3c53ba --- /dev/null +++ b/backend/src/main/java/com/reactpairdemo/demo/utils/Mapper.java @@ -0,0 +1,19 @@ +package com.reactpairdemo.demo.utils; + +import com.reactpairdemo.demo.dto.UserDto; +import com.reactpairdemo.demo.entity.User; +import org.modelmapper.ModelMapper; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +@Component +public class Mapper { + @Autowired + private ModelMapper modelMapper; + public UserDto entityToDto(User user){ + return modelMapper.map(user, UserDto.class); + } + public User dtoToEntity(UserDto user){ + return modelMapper.map(user, User.class); + } +} diff --git a/backend/src/main/resources/application.properties b/backend/src/main/resources/application.properties index 89eef6b..8dd396d 100644 --- a/backend/src/main/resources/application.properties +++ b/backend/src/main/resources/application.properties @@ -3,4 +3,5 @@ spring.datasource.url=jdbc:mysql://localhost:3306/pairdemo?useSSL=false&ServerTi spring.datasource.username=root spring.datasource.password=root spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL8Dialect -spring.jpa.hibernate.ddl-auto=update \ No newline at end of file +spring.jpa.hibernate.ddl-auto=update +# make demo user email ,password and name with validations and secure password followed naming convention \ No newline at end of file diff --git a/backend/target/classes/application.properties b/backend/target/classes/application.properties index 89eef6b..8dd396d 100644 --- a/backend/target/classes/application.properties +++ b/backend/target/classes/application.properties @@ -3,4 +3,5 @@ spring.datasource.url=jdbc:mysql://localhost:3306/pairdemo?useSSL=false&ServerTi spring.datasource.username=root spring.datasource.password=root spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL8Dialect -spring.jpa.hibernate.ddl-auto=update \ No newline at end of file +spring.jpa.hibernate.ddl-auto=update +# make demo user email ,password and name with validations and secure password followed naming convention \ No newline at end of file diff --git a/backend/target/classes/com/reactpairdemo/demo/DemoApplication.class b/backend/target/classes/com/reactpairdemo/demo/DemoApplication.class index 5662ef5..3d71273 100644 Binary files a/backend/target/classes/com/reactpairdemo/demo/DemoApplication.class and b/backend/target/classes/com/reactpairdemo/demo/DemoApplication.class differ diff --git a/backend/target/classes/com/reactpairdemo/demo/controller/UserController.class b/backend/target/classes/com/reactpairdemo/demo/controller/UserController.class new file mode 100644 index 0000000..54fe34f Binary files /dev/null and b/backend/target/classes/com/reactpairdemo/demo/controller/UserController.class differ diff --git a/backend/target/classes/com/reactpairdemo/demo/dto/UserDto.class b/backend/target/classes/com/reactpairdemo/demo/dto/UserDto.class new file mode 100644 index 0000000..d528cb8 Binary files /dev/null and b/backend/target/classes/com/reactpairdemo/demo/dto/UserDto.class differ diff --git a/backend/target/classes/com/reactpairdemo/demo/entity/User.class b/backend/target/classes/com/reactpairdemo/demo/entity/User.class new file mode 100644 index 0000000..ed064bb Binary files /dev/null and b/backend/target/classes/com/reactpairdemo/demo/entity/User.class differ diff --git a/backend/target/classes/com/reactpairdemo/demo/exception/ErrorResponse$ErrorResponseBuilder.class b/backend/target/classes/com/reactpairdemo/demo/exception/ErrorResponse$ErrorResponseBuilder.class new file mode 100644 index 0000000..1038fab Binary files /dev/null and b/backend/target/classes/com/reactpairdemo/demo/exception/ErrorResponse$ErrorResponseBuilder.class differ diff --git a/backend/target/classes/com/reactpairdemo/demo/exception/ErrorResponse.class b/backend/target/classes/com/reactpairdemo/demo/exception/ErrorResponse.class new file mode 100644 index 0000000..2efc5db Binary files /dev/null and b/backend/target/classes/com/reactpairdemo/demo/exception/ErrorResponse.class differ diff --git a/backend/target/classes/com/reactpairdemo/demo/exception/GlobalExceptionHandler.class b/backend/target/classes/com/reactpairdemo/demo/exception/GlobalExceptionHandler.class new file mode 100644 index 0000000..d06e342 Binary files /dev/null and b/backend/target/classes/com/reactpairdemo/demo/exception/GlobalExceptionHandler.class differ diff --git a/backend/target/classes/com/reactpairdemo/demo/exception/UserException.class b/backend/target/classes/com/reactpairdemo/demo/exception/UserException.class new file mode 100644 index 0000000..76bfaa9 Binary files /dev/null and b/backend/target/classes/com/reactpairdemo/demo/exception/UserException.class differ diff --git a/backend/target/classes/com/reactpairdemo/demo/repository/UserRepository.class b/backend/target/classes/com/reactpairdemo/demo/repository/UserRepository.class new file mode 100644 index 0000000..7b82940 Binary files /dev/null and b/backend/target/classes/com/reactpairdemo/demo/repository/UserRepository.class differ diff --git a/backend/target/classes/com/reactpairdemo/demo/service/UserService.class b/backend/target/classes/com/reactpairdemo/demo/service/UserService.class new file mode 100644 index 0000000..5f1f559 Binary files /dev/null and b/backend/target/classes/com/reactpairdemo/demo/service/UserService.class differ diff --git a/backend/target/classes/com/reactpairdemo/demo/service/impl/UserServiceImpl.class b/backend/target/classes/com/reactpairdemo/demo/service/impl/UserServiceImpl.class new file mode 100644 index 0000000..1facdf6 Binary files /dev/null and b/backend/target/classes/com/reactpairdemo/demo/service/impl/UserServiceImpl.class differ diff --git a/backend/target/classes/com/reactpairdemo/demo/utils/Constants.class b/backend/target/classes/com/reactpairdemo/demo/utils/Constants.class new file mode 100644 index 0000000..08e6eb7 Binary files /dev/null and b/backend/target/classes/com/reactpairdemo/demo/utils/Constants.class differ diff --git a/backend/target/classes/com/reactpairdemo/demo/utils/Mapper.class b/backend/target/classes/com/reactpairdemo/demo/utils/Mapper.class new file mode 100644 index 0000000..195ec03 Binary files /dev/null and b/backend/target/classes/com/reactpairdemo/demo/utils/Mapper.class differ