-
Notifications
You must be signed in to change notification settings - Fork 114
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Initial commit * feat: set up the project * 경북대BE_안용진_2주차 과제(step0) (#74) * Initial commit * 경북대BE_안용진_1주차 과제 (#197) * docs(README.md): fill README.md with features that should be implemented * docs(README.md): add some response details * feat: add ProductRecord class for storing product information and some code for testing if record class works well * feat: dd feature to check existence of record by ID * feat: add feature to create new id * feat: change id type from String to long * feat: add feature to insert records with specified ID * feat: add feature to insert records with automatically specified ID * feat: implement post handler method * feat: implement get request handler * feat: add feature to handling DELETE request * refactor: change addNewRecord to throw Exception instead of to return null * feat: implement feature to handle PUT * refactor: extract feature that make created response entity to function * feat: implement feature to handle PATCH * feat: add global exception handler * refactor: extract withId method to Record class for creating new objects with specific id * refactor : reorder methods for better readability and understanding * docs: add extra features * refactor: restructure project packages * Step2 시작 * feat: create necessary files for server side rendering * feat: add simple table that shows information of products * feat: make simple edit page * fix: fix getNewId() to correctly find new id * fix: ensure null is passed when input is empty * feat: add simple product add page * feat: add buttons to manipulate data * docs: fill README with list of features for step2 * style: apply styling using CSS * style: apply styling on product add page using CSS * style: apply styling on product edit page * Step3 시작 * feat: connect Record get functions to jdbcTemplates * feat: integrate addNewRecord method with JDBC * feat: integrate replaceRecord method that update all field of record with jdbc * feat: Integrate edit record feature with JDBC * feat: integrate feature deleting record with JDBC * refactor: edit getNewId not to make overflow * fix: correct table name typo * fix: adjust some bug * feat: set auto schema initialization using schema.sql * refactor: change field-based injection to constructor-based injection * refactor: Ensure consistency by updating all Rest methods to use ResponseEntity * feat: Implement global handler method for all subclasses of Exception * docs: add TODO comments * refactor: Remove unused fields * refactor: Remove unused fields * refactor: Change all field injections to constructor injections * refactor: Replace all array structures with List * feat: Change to generate keys in the database --------- Co-authored-by: 박재성(Jason) <[email protected]> * 경북대 BE_안용진 2주차 과제(1단계) (#209) * feat: Display error messages to users when receiving an error response * docs: fill README with list of features for step1 * feat: Apply validation using BeanValidation * build: Add boot-starter-validation dependency * feat: Add exception handler for MethodArgumentNotValidException * feat: Implement response handling for 400 errors on admin page * fix: Correct minor text typos * 경북대 BE_안용진 2주차 과제 (2, 3단계) (#376) * 2단계 시작 * feat: Add users table definition to schema.sql * feat: Add users table definition to schema.sql * refactor: Update data types to comply with SQL standards * refactor: Rename model package to entity package * feat: Implement API to retrieve all users * feat: add Request Http for test getUsers API * refactor: add UserService class * refactor: Modify API request URLs to start with /api * feat: Add signup * feat: Respond with 409 Conflict for duplicate email signups * feat: Add account deletion * feat: Implement password change functionality (JWT token not yet applied) * feat: Implement login * feat: Add exception handler to response 403 for forbidden requests or password errors * refactor: Redistribute responsibilities * refactor: Rename JWT package to lowercase * feat: Apply authentication filter * feat: Implement TokenEmail Resolver to extract email from token and pass as method argument * feat: Implement user-specific wishlist retrieval * feat: Implement wishlist addition * feat: Implement wishlist deletion * fix: fix sql typos * refactor: Update API paths * refactor: Reorganize packages * refactor: remove unneccessary folder --------- Co-authored-by: 박재성(Jason) <[email protected]>
- Loading branch information
Showing
45 changed files
with
1,704 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1 @@ | ||
# spring-gift-jpa | ||
# spring-gift-jpa |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
package gift.annotation; | ||
|
||
import java.lang.annotation.ElementType; | ||
import java.lang.annotation.Retention; | ||
import java.lang.annotation.RetentionPolicy; | ||
import java.lang.annotation.Target; | ||
|
||
@Target(ElementType.PARAMETER) | ||
@Retention(RetentionPolicy.RUNTIME) | ||
public @interface TokenEmail { | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
package gift.config; | ||
|
||
import gift.resolver.TokenEmailResolver; | ||
import gift.security.authfilter.AuthenticationFilter; | ||
import gift.security.jwt.TokenExtractor; | ||
import org.springframework.boot.web.servlet.FilterRegistrationBean; | ||
import org.springframework.context.annotation.Bean; | ||
import org.springframework.context.annotation.Configuration; | ||
import org.springframework.web.method.support.HandlerMethodArgumentResolver; | ||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; | ||
|
||
import java.util.List; | ||
|
||
@Configuration | ||
public class WebConfig implements WebMvcConfigurer { | ||
private final TokenExtractor tokenExtractor; | ||
|
||
public WebConfig(TokenExtractor tokenExtractor) { | ||
this.tokenExtractor = tokenExtractor; | ||
} | ||
|
||
@Bean | ||
public FilterRegistrationBean<AuthenticationFilter> authenticationFilterRegistrationBean(TokenExtractor tokenExtractor) { | ||
FilterRegistrationBean<AuthenticationFilter> registrationBean = new FilterRegistrationBean<>(); | ||
|
||
registrationBean.setFilter(new AuthenticationFilter(tokenExtractor)); | ||
registrationBean.addUrlPatterns("/api/*"); | ||
registrationBean.setOrder(1); | ||
|
||
return registrationBean; | ||
} | ||
|
||
@Override | ||
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) { | ||
argumentResolvers.add(new TokenEmailResolver(tokenExtractor)); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
package gift.controller.page; | ||
|
||
import gift.entity.ProductRecord; | ||
import gift.repository.ProductDAO; | ||
import org.springframework.stereotype.Controller; | ||
import org.springframework.ui.Model; | ||
import org.springframework.web.bind.annotation.GetMapping; | ||
import org.springframework.web.bind.annotation.PathVariable; | ||
|
||
import java.util.List; | ||
|
||
@Controller | ||
public class AdminController { | ||
private final ProductDAO productDAO; | ||
|
||
AdminController(ProductDAO productDAO) { | ||
this.productDAO = productDAO; | ||
} | ||
|
||
@GetMapping("/") | ||
public String admin(Model model) { | ||
List<ProductRecord> products = productDAO.getAllRecords(); | ||
|
||
model.addAttribute("products", products); | ||
return "admin"; | ||
} | ||
|
||
@GetMapping("/products/{id}/edit") | ||
public String editProduct(@PathVariable int id, Model model) { | ||
ProductRecord product = productDAO.getRecord(id); | ||
model.addAttribute("product", product); | ||
|
||
return "product_edit"; | ||
} | ||
|
||
@GetMapping("/products/add") | ||
public String addProduct(Model model) { | ||
return "product_add"; | ||
} | ||
} |
68 changes: 68 additions & 0 deletions
68
src/main/java/gift/controller/product/ProductController.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
package gift.controller.product; | ||
|
||
import gift.entity.ProductRecord; | ||
import gift.repository.ProductDAO; | ||
import jakarta.validation.Valid; | ||
import org.springframework.http.ResponseEntity; | ||
import org.springframework.web.bind.annotation.*; | ||
import org.springframework.web.servlet.support.ServletUriComponentsBuilder; | ||
|
||
import java.net.URI; | ||
import java.util.List; | ||
import java.util.NoSuchElementException; | ||
|
||
@RestController | ||
public class ProductController { | ||
private final ProductDAO productDAO; | ||
|
||
ProductController(ProductDAO productDAO) { | ||
this.productDAO = productDAO; | ||
} | ||
|
||
@GetMapping("/api/products") | ||
public ResponseEntity<List<ProductRecord>> getAllProducts() { | ||
return ResponseEntity.ok(productDAO.getAllRecords()); | ||
} | ||
|
||
@PostMapping("/api/products") | ||
public ResponseEntity<ProductRecord> addProduct(@Valid @RequestBody ProductRecord product) { | ||
ProductRecord result = productDAO.addNewRecord(product); | ||
|
||
return makeCreatedResponse(result); | ||
} | ||
|
||
@DeleteMapping("/api/products/{id}") | ||
public ResponseEntity<Void> deleteProduct(@PathVariable int id) { | ||
productDAO.deleteRecord(id); | ||
|
||
return ResponseEntity.noContent().build(); | ||
} | ||
|
||
@PutMapping("/api/products/{id}") | ||
public ResponseEntity<ProductRecord> updateProduct(@PathVariable int id, @Valid @RequestBody ProductRecord product) { | ||
ProductRecord result; | ||
try { | ||
result = productDAO.replaceRecord(id, product); | ||
|
||
return ResponseEntity.ok(result); | ||
} catch (NoSuchElementException e) { | ||
result = productDAO.addNewRecord(product, id); | ||
|
||
return makeCreatedResponse(result); | ||
} | ||
} | ||
|
||
@PatchMapping("/api/products/{id}") | ||
public ResponseEntity<ProductRecord> updateProductPartially(@PathVariable int id, @Valid @RequestBody ProductRecord patch) { | ||
return ResponseEntity.ok(productDAO.updateRecord(id, patch)); | ||
} | ||
|
||
private ResponseEntity<ProductRecord> makeCreatedResponse(ProductRecord product) { | ||
URI location = ServletUriComponentsBuilder.fromCurrentRequest() | ||
.path("/products/"+ product.id()) | ||
.build() | ||
.toUri(); | ||
|
||
return ResponseEntity.created(location).body(product); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
package gift.controller.user; | ||
|
||
import gift.dto.user.TokenResponseDTO; | ||
import gift.dto.user.UserRequestDTO; | ||
import gift.exception.InvalidPasswordException; | ||
import gift.service.UserService; | ||
import jakarta.validation.Valid; | ||
import org.springframework.http.ResponseEntity; | ||
import org.springframework.web.bind.annotation.PostMapping; | ||
import org.springframework.web.bind.annotation.RequestBody; | ||
import org.springframework.web.bind.annotation.RestController; | ||
|
||
@RestController | ||
public class AuthController { | ||
private final UserService userService; | ||
|
||
public AuthController(UserService userService) { | ||
this.userService = userService; | ||
} | ||
|
||
@PostMapping("/signup") | ||
public ResponseEntity<TokenResponseDTO> signUp(@RequestBody @Valid UserRequestDTO userRequestDTO) { | ||
TokenResponseDTO tokenResponseDTO = userService.signUp(userRequestDTO); | ||
|
||
return ResponseEntity.ok(tokenResponseDTO); | ||
} | ||
|
||
|
||
@PostMapping("/login") | ||
public ResponseEntity<TokenResponseDTO> login(@RequestBody @Valid UserRequestDTO userRequestDTO) throws InvalidPasswordException { | ||
TokenResponseDTO tokenResponseDTO = userService.login(userRequestDTO); | ||
|
||
return ResponseEntity.ok(tokenResponseDTO); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
package gift.controller.user; | ||
|
||
import gift.annotation.TokenEmail; | ||
import gift.dto.user.PwUpdateDTO; | ||
import gift.dto.user.UserResponseDTO; | ||
import gift.exception.ForbiddenRequestException; | ||
import gift.service.UserService; | ||
import jakarta.validation.Valid; | ||
import org.springframework.http.ResponseEntity; | ||
import org.springframework.web.bind.annotation.*; | ||
|
||
import java.util.List; | ||
|
||
@RestController | ||
public class UserController { | ||
private final UserService userService; | ||
|
||
public UserController(UserService userService) { | ||
this.userService = userService; | ||
} | ||
|
||
@GetMapping("/api/users") | ||
public ResponseEntity<List<UserResponseDTO>> getUsers() { | ||
return ResponseEntity.ok(userService.getAllUsers()); | ||
} | ||
|
||
|
||
|
||
@DeleteMapping("/api/users") | ||
public ResponseEntity<Void> deleteUser(@TokenEmail String email) { | ||
userService.deleteUser(email); | ||
return ResponseEntity.noContent().build(); | ||
} | ||
|
||
@PatchMapping("/api/password-change") | ||
public ResponseEntity<String> updatePw(@TokenEmail String email, @RequestBody @Valid PwUpdateDTO pwUpdateDTO) { | ||
final boolean FORBIDDEN = true; | ||
|
||
if (FORBIDDEN) { | ||
throw new ForbiddenRequestException("password changing is not allowed"); | ||
} | ||
|
||
userService.updatePw(email, pwUpdateDTO); | ||
|
||
return ResponseEntity.ok("Password updated successfully"); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
package gift.controller.wish; | ||
|
||
import gift.annotation.TokenEmail; | ||
import gift.dto.wish.WishRequestDTO; | ||
import gift.dto.wish.WishResponseDTO; | ||
import gift.service.WishService; | ||
import org.springframework.http.ResponseEntity; | ||
import org.springframework.web.bind.annotation.*; | ||
import org.springframework.web.servlet.support.ServletUriComponentsBuilder; | ||
|
||
import java.net.URI; | ||
import java.util.List; | ||
|
||
@RestController | ||
public class WishController { | ||
private final WishService wishService; | ||
|
||
public WishController(WishService wishService) { | ||
this.wishService = wishService; | ||
} | ||
|
||
@GetMapping("/api/wishes") | ||
public ResponseEntity<List<WishResponseDTO>> getWishes(@TokenEmail String email) { | ||
return ResponseEntity.ok(wishService.getWishes(email)); | ||
} | ||
|
||
@PostMapping("/api/wishes") | ||
public ResponseEntity<WishResponseDTO> addWish(@TokenEmail String email, @RequestBody WishRequestDTO wishRequestDTO) { | ||
return makeCreatedResponse(wishService.addWish(email, wishRequestDTO)); | ||
} | ||
|
||
@DeleteMapping("/api/wishes/{wishId}") | ||
public ResponseEntity<Void> deleteWish(@TokenEmail String email, @PathVariable long wishId) { | ||
wishService.deleteWish(email, wishId); | ||
|
||
return ResponseEntity.noContent().build(); | ||
} | ||
|
||
private ResponseEntity<WishResponseDTO> makeCreatedResponse(WishResponseDTO wish) { | ||
URI location = ServletUriComponentsBuilder.fromCurrentRequest() | ||
.path("/api/wishes/"+ wish.id()) | ||
.build() | ||
.toUri(); | ||
|
||
return ResponseEntity.created(location).body(wish); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
package gift.dto.user; | ||
|
||
public record EncryptedUpdateDTO( | ||
long id, | ||
String encryptedPw | ||
) { | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
package gift.dto.user; | ||
|
||
import jakarta.validation.constraints.Pattern; | ||
|
||
public record PwUpdateDTO( | ||
@Pattern(regexp = "^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9]).{8,15}$", message = "비밀번호는 8 ~ 15자로, 대문자, 소문자, 숫자가 반드시 포함되어야 합니다.") | ||
String password | ||
) { | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
package gift.dto.user; | ||
|
||
public record TokenResponseDTO(String token) { | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
package gift.dto.user; | ||
|
||
public record UserEncryptedDTO( | ||
String email, | ||
String encryptedPW | ||
) { } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
package gift.dto.user; | ||
|
||
public record UserInfoDTO( | ||
long id, | ||
String email, | ||
String encryptedPw | ||
) { | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
package gift.dto.user; | ||
|
||
import jakarta.validation.constraints.Email; | ||
import jakarta.validation.constraints.Pattern; | ||
|
||
public record UserRequestDTO( | ||
@Email(message = "email 형식에 맞지 않습니다.") | ||
String email, | ||
|
||
@Pattern(regexp = "^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9]).{8,15}$", message = "비밀번호는 8 ~ 15자로, 대문자, 소문자, 숫자가 반드시 포함되어야 합니다.") | ||
String password | ||
) { | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
package gift.dto.user; | ||
|
||
public record UserResponseDTO( | ||
long id, | ||
String email | ||
) { | ||
public UserResponseDTO { | ||
if (id < 0) { | ||
throw new IllegalArgumentException("Id cannot be negative"); | ||
} | ||
|
||
if (email == null) { | ||
throw new IllegalArgumentException("Email cannot be null"); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
package gift.dto.wish; | ||
|
||
public record WishCreateDTO( | ||
long userId, | ||
long productId, | ||
int quantity | ||
) { | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
package gift.dto.wish; | ||
|
||
public record WishInfoDTO( | ||
long id, | ||
long userId, | ||
long productId, | ||
int quantity | ||
) { | ||
} |
Oops, something went wrong.