-
Notifications
You must be signed in to change notification settings - Fork 0
feat(user): 슈퍼계정 생성 #51
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
The head ref may contain hidden characters: "feat/#47_\uAD00\uB9AC\uC790\uD398\uC774\uC9C0\uC8FC\uBB38\uC870\uD68C"
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| --- | ||
| name: 백엔드 이슈 | ||
| about: 백엔드와 관련된 이슈 | ||
| title: "[백엔드] " | ||
| labels: Backend | ||
| assignees: '' | ||
|
|
||
| --- | ||
|
|
||
| # 이슈 내용 | ||
|
|
||
|
|
||
| # 작업 목록 | ||
| - [ ] |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,39 @@ | ||
| package com.example.apiuser; | ||
|
|
||
| import org.springframework.boot.SpringApplication; | ||
| import org.springframework.boot.autoconfigure.SpringBootApplication; | ||
| import org.springframework.boot.autoconfigure.domain.EntityScan; | ||
| import org.springframework.data.jpa.repository.config.EnableJpaAuditing; | ||
| import org.springframework.data.jpa.repository.config.EnableJpaRepositories; | ||
|
|
||
| @EnableJpaAuditing | ||
| @SpringBootApplication(scanBasePackages = { | ||
| "com.example.apiuser", | ||
| "com.nowait.auth" | ||
| }) | ||
| @EntityScan(basePackages = { | ||
| "com.example.menu.entity", // domain-menu | ||
| "com.example.domainstore.entity", // domain-store | ||
| "com.example.domaintoken.entity", | ||
| "com.nowaiting.user.entity", | ||
| "com.nowait.domainbookmark.entity", | ||
| "com.nowait.domainreservation.entity", | ||
| "com.nowait.domainorder.entity", | ||
| "com.nowait.domainorder.entity" | ||
| }) | ||
| @EnableJpaRepositories(basePackages = { | ||
| "com.example.menu.repository", | ||
| "com.nowaiting.user.repository", | ||
| "com.example.domainstore.repository", | ||
| "com.example.domaintoken.repository", | ||
| "com.nowait.domainbookmark.repository", | ||
| "com.nowait.domainorder.repository", | ||
| "com.nowait.domainreservation.repository" | ||
| }) | ||
| public class ApiUserApplication { | ||
|
|
||
| public static void main(String[] args) { | ||
| SpringApplication.run(ApiUserApplication.class, args); | ||
| } | ||
|
|
||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,67 @@ | ||
| package com.example.apiuser.bookmark.controller; | ||
|
|
||
| import org.springframework.http.HttpStatus; | ||
| import org.springframework.http.ResponseEntity; | ||
| import org.springframework.security.core.annotation.AuthenticationPrincipal; | ||
| import org.springframework.web.bind.annotation.DeleteMapping; | ||
| import org.springframework.web.bind.annotation.GetMapping; | ||
| import org.springframework.web.bind.annotation.PathVariable; | ||
| import org.springframework.web.bind.annotation.PostMapping; | ||
| import org.springframework.web.bind.annotation.RequestMapping; | ||
| import org.springframework.web.bind.annotation.RestController; | ||
|
|
||
| import com.example.apiuser.bookmark.dto.BookmarkCreateResponse; | ||
| import com.example.apiuser.bookmark.service.BookmarkService; | ||
| import com.nowait.auth.dto.CustomOAuth2User; | ||
| import com.nowaiting.common.api.ApiUtils; | ||
|
|
||
| import io.swagger.v3.oas.annotations.Operation; | ||
| import io.swagger.v3.oas.annotations.responses.ApiResponse; | ||
| import io.swagger.v3.oas.annotations.tags.Tag; | ||
| import lombok.RequiredArgsConstructor; | ||
| @Tag(name = "Bookmark API", description = "북마크 API") | ||
| @RestController | ||
| @RequestMapping("/bookmarks") | ||
| @RequiredArgsConstructor | ||
| public class BookmarkController { | ||
| private final BookmarkService bookmarkService; | ||
|
|
||
| @PostMapping("/{storeId}") | ||
| @Operation(summary = "북마크 생성", description = "특정 주점에 대한 북마크 생성") | ||
| @ApiResponse(responseCode = "201", description = "북마크 생성") | ||
| public ResponseEntity<?> createBookmark(@PathVariable Long storeId,@AuthenticationPrincipal CustomOAuth2User customOAuth2User) { | ||
| BookmarkCreateResponse response = bookmarkService.createBookmark(storeId,customOAuth2User); | ||
|
|
||
| return ResponseEntity | ||
| .status(HttpStatus.CREATED) | ||
| .body( | ||
| ApiUtils.success( | ||
| response | ||
| ) | ||
| ); | ||
| } | ||
| @GetMapping | ||
| @Operation(summary = "북마크 조회", description = "내가 북마크한 주점 조회") | ||
| @ApiResponse(responseCode = "200", description = "북마크 조회") | ||
| public ResponseEntity<?> getAllBookmarks(@AuthenticationPrincipal CustomOAuth2User customOAuth2User) { | ||
| return ResponseEntity | ||
| .ok() | ||
| .body( | ||
| ApiUtils.success( | ||
| bookmarkService.getBookmarks(customOAuth2User) | ||
| ) | ||
| ); | ||
| } | ||
| @DeleteMapping("/{bookmarkId}") | ||
| @Operation(summary = "북마크 삭제", description = "특정 주점에 대한 북마크 삭제") | ||
| @ApiResponse(responseCode = "200", description = "북마크 삭제") | ||
| public ResponseEntity<?> deleteBookmark(@PathVariable Long bookmarkId, @AuthenticationPrincipal CustomOAuth2User customOAuth2User) { | ||
| return ResponseEntity | ||
| .ok() | ||
| .body( | ||
| ApiUtils.success( | ||
| bookmarkService.deleteBookmark(bookmarkId,customOAuth2User) | ||
| ) | ||
| ); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| package com.example.apiuser.bookmark.dto; | ||
|
|
||
| import com.nowait.domainbookmark.entity.Bookmark; | ||
|
|
||
| import lombok.AllArgsConstructor; | ||
| import lombok.Builder; | ||
| import lombok.Getter; | ||
|
|
||
| @Getter | ||
| @AllArgsConstructor | ||
| @Builder | ||
| public class BookmarkCreateResponse { | ||
| private Long bookmarkId; | ||
| private Long userId; | ||
| private Long storeId; | ||
|
|
||
| public static BookmarkCreateResponse fromEntity(Bookmark bookmark) { | ||
| return BookmarkCreateResponse.builder() | ||
| .bookmarkId(bookmark.getId()) | ||
| .userId(bookmark.getUser().getId()) | ||
| .storeId(bookmark.getStore().getStoreId()) | ||
| .build(); | ||
| } | ||
| } | ||
|
Comment on lines
+9
to
+24
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion 코드 중복을 제거하여 DRY 원칙을 준수해주세요.
다음 방법 중 하나를 고려해보세요: 방법 1: 공통 클래스 사용 // BookmarkResponse로 통합
public class BookmarkResponse {
private Long bookmarkId;
private Long userId;
private Long storeId;
// ... 동일한 구현
}방법 2: 공통 인터페이스 또는 추상 클래스 public abstract class BaseBookmarkResponse {
protected Long bookmarkId;
protected Long userId;
protected Long storeId;
// ... 공통 구현
}이렇게 하면 코드 중복을 제거하고 유지보수성을 향상시킬 수 있습니다. 🤖 Prompt for AI Agents |
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| package com.example.apiuser.bookmark.dto; | ||
|
|
||
| import com.nowait.domainbookmark.entity.Bookmark; | ||
|
|
||
| import lombok.AllArgsConstructor; | ||
| import lombok.Builder; | ||
| import lombok.Getter; | ||
|
|
||
| @Getter | ||
| @AllArgsConstructor | ||
| @Builder | ||
| public class BookmarkGetResponse { | ||
| private Long bookmarkId; | ||
| private Long userId; | ||
| private Long storeId; | ||
|
|
||
| public static BookmarkGetResponse fromEntity(Bookmark bookmark) { | ||
| return BookmarkGetResponse.builder() | ||
| .bookmarkId(bookmark.getId()) | ||
| .userId(bookmark.getUser().getId()) | ||
| .storeId(bookmark.getStore().getStoreId()) | ||
| .build(); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,78 @@ | ||||||||||||||||||||||||||||||||||||||
| package com.example.apiuser.bookmark.service; | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| import java.util.List; | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| import org.springframework.stereotype.Service; | ||||||||||||||||||||||||||||||||||||||
| import org.springframework.transaction.annotation.Transactional; | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| import com.example.apiuser.bookmark.dto.BookmarkCreateResponse; | ||||||||||||||||||||||||||||||||||||||
| import com.example.apiuser.bookmark.dto.BookmarkGetResponse; | ||||||||||||||||||||||||||||||||||||||
| import com.example.domainstore.entity.Store; | ||||||||||||||||||||||||||||||||||||||
| import com.example.domainstore.repository.StoreRepository; | ||||||||||||||||||||||||||||||||||||||
| import com.nowait.auth.dto.CustomOAuth2User; | ||||||||||||||||||||||||||||||||||||||
| import com.nowait.domainbookmark.entity.Bookmark; | ||||||||||||||||||||||||||||||||||||||
| import com.nowait.domainbookmark.repository.BookmarkRepository; | ||||||||||||||||||||||||||||||||||||||
| import com.nowaiting.user.entity.User; | ||||||||||||||||||||||||||||||||||||||
| import com.nowaiting.user.repository.UserRepository; | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| import jakarta.persistence.EntityNotFoundException; | ||||||||||||||||||||||||||||||||||||||
| import lombok.RequiredArgsConstructor; | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| @Service | ||||||||||||||||||||||||||||||||||||||
| @RequiredArgsConstructor | ||||||||||||||||||||||||||||||||||||||
| public class BookmarkService { | ||||||||||||||||||||||||||||||||||||||
| private final BookmarkRepository bookmarkRepository; | ||||||||||||||||||||||||||||||||||||||
| private final StoreRepository storeRepository; | ||||||||||||||||||||||||||||||||||||||
| private final UserRepository userRepository; | ||||||||||||||||||||||||||||||||||||||
| @Transactional | ||||||||||||||||||||||||||||||||||||||
| public BookmarkCreateResponse createBookmark(Long storeId, CustomOAuth2User customOAuth2User) { | ||||||||||||||||||||||||||||||||||||||
| parameterValidation(storeId, customOAuth2User); | ||||||||||||||||||||||||||||||||||||||
| Store store = storeRepository.findById(storeId) | ||||||||||||||||||||||||||||||||||||||
| .orElseThrow(() -> new EntityNotFoundException(storeId + " store not found.")); | ||||||||||||||||||||||||||||||||||||||
| User user = userRepository.findById(customOAuth2User.getUserId()) | ||||||||||||||||||||||||||||||||||||||
| .orElseThrow(() -> new EntityNotFoundException("User not found")); | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| if (bookmarkRepository.existsByUserAndStore(user, store)) { | ||||||||||||||||||||||||||||||||||||||
| throw new IllegalArgumentException("already bookmarked"); | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| Bookmark bookmark = Bookmark.builder() | ||||||||||||||||||||||||||||||||||||||
| .store(store) | ||||||||||||||||||||||||||||||||||||||
| .user(user) | ||||||||||||||||||||||||||||||||||||||
| .build(); | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| return BookmarkCreateResponse.fromEntity(bookmarkRepository.save(bookmark)); | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| @Transactional(readOnly = true) | ||||||||||||||||||||||||||||||||||||||
| public List<BookmarkGetResponse> getBookmarks(CustomOAuth2User customOAuth2User) { | ||||||||||||||||||||||||||||||||||||||
| User user = userRepository.findById(customOAuth2User.getUserId()) | ||||||||||||||||||||||||||||||||||||||
| .orElseThrow(() -> new EntityNotFoundException("User not found")); | ||||||||||||||||||||||||||||||||||||||
| return bookmarkRepository.findAllByUser(user) | ||||||||||||||||||||||||||||||||||||||
| .stream() | ||||||||||||||||||||||||||||||||||||||
| .map(BookmarkGetResponse::fromEntity) | ||||||||||||||||||||||||||||||||||||||
| .toList(); | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| @Transactional | ||||||||||||||||||||||||||||||||||||||
| public String deleteBookmark(Long bookmarkId, CustomOAuth2User customOAuth2User) { | ||||||||||||||||||||||||||||||||||||||
| parameterValidation(bookmarkId, customOAuth2User); | ||||||||||||||||||||||||||||||||||||||
| Bookmark bookmark = bookmarkRepository.findById(bookmarkId) | ||||||||||||||||||||||||||||||||||||||
| .orElseThrow(() -> new EntityNotFoundException(bookmarkId + " bookmark not found.")); | ||||||||||||||||||||||||||||||||||||||
| if (bookmark.getUser().getId() != customOAuth2User.getUserId()) { | ||||||||||||||||||||||||||||||||||||||
| throw new IllegalArgumentException("you can only delete your own bookmark"); | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+62
to
+64
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 사용자 권한 검증에서 타입 안전성 문제가 있습니다.
-if (bookmark.getUser().getId() != customOAuth2User.getUserId()) {
+if (!Objects.equals(bookmark.getUser().getId(), customOAuth2User.getUserId())) {
throw new IllegalArgumentException("you can only delete your own bookmark");
}파일 상단에 🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||
| bookmarkRepository.delete(bookmark); | ||||||||||||||||||||||||||||||||||||||
| return "Bookmark ID " + bookmarkId + " deleted."; | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| private static void parameterValidation(Long storeId, CustomOAuth2User customOAuth2User) { | ||||||||||||||||||||||||||||||||||||||
| // 파라미터 유효성 검사 | ||||||||||||||||||||||||||||||||||||||
| if (storeId == null || storeId < 0) { | ||||||||||||||||||||||||||||||||||||||
| throw new IllegalArgumentException("storeId must be a positive number"); | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
| if (customOAuth2User == null || customOAuth2User.getUserId() == null) { | ||||||||||||||||||||||||||||||||||||||
| throw new IllegalArgumentException("UserInfo is required"); | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+69
to
+77
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion 매개변수 검증 로직을 개선할 수 있습니다. 현재 검증 로직은 중복 코드를 포함하고 있으며, 메서드명이 용도를 명확히 나타내지 않습니다. 또한 storeId가 0인 경우에 대한 처리가 애매합니다. -private static void parameterValidation(Long storeId, CustomOAuth2User customOAuth2User) {
+private static void validateParameters(Long id, CustomOAuth2User customOAuth2User) {
// 파라미터 유효성 검사
- if (storeId == null || storeId < 0) {
- throw new IllegalArgumentException("storeId must be a positive number");
+ if (id == null || id <= 0) {
+ throw new IllegalArgumentException("ID must be a positive number");
}
if (customOAuth2User == null || customOAuth2User.getUserId() == null) {
throw new IllegalArgumentException("UserInfo is required");
}
}메서드 호출 부분도 업데이트해야 합니다. 📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
엔티티 스캔 중복 제거 필요
"com.nowait.domainorder.entity"패키지가 21번과 22번 라인에 중복으로 선언되어 있습니다."com.nowait.domainbookmark.entity", "com.nowait.domainreservation.entity", "com.nowait.domainorder.entity", - "com.nowait.domainorder.entity"📝 Committable suggestion
🤖 Prompt for AI Agents