-
Notifications
You must be signed in to change notification settings - Fork 6
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
[BE] Feat/#378 Admin API 구현 #405
Changes from 15 commits
1000bed
0a7f1cb
540a644
1dd3c73
1c50017
309b827
1535ada
d688eee
06ef99b
c7c8ee8
7f2c47b
523ce2c
0e887ea
190f5d3
1932e58
bb6fb8d
0f54571
a1b2b54
1e23aee
605a2e3
e5a898d
53f9c42
f7afa50
9084afd
b30c821
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,29 @@ | ||
== 관리자 기능 | ||
|
||
=== 전체 회원 조회 | ||
|
||
operation::admin-controller-test/find-all-member-details[snippets='http-request,http-response'] | ||
|
||
=== 회원 상세 조회 | ||
|
||
operation::admin-controller-test/find-member[snippets='http-request,http-response'] | ||
|
||
=== 회원 차단(삭제) | ||
|
||
operation::admin-controller-test/delete-member[snippets='http-request,http-response'] | ||
|
||
=== 토픽 삭제 | ||
|
||
operation::admin-controller-test/delete-topic[snippets='http-request,http-response'] | ||
|
||
=== 토픽 이미지 삭제 | ||
|
||
operation::admin-controller-test/delete-topic-image[snippets='http-request,http-response'] | ||
|
||
=== 핀 삭제 | ||
|
||
operation::admin-controller-test/delete-pin[snippets='http-request,http-response'] | ||
|
||
=== 핀 이미지 삭제 | ||
|
||
operation::admin-controller-test/delete-pin-image[snippets='http-request,http-response'] |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
package com.mapbefine.mapbefine.admin.application; | ||
|
||
import static com.mapbefine.mapbefine.permission.exception.PermissionErrorCode.PERMISSION_FORBIDDEN_BY_NOT_ADMIN; | ||
import static com.mapbefine.mapbefine.topic.exception.TopicErrorCode.TOPIC_NOT_FOUND; | ||
|
||
import com.mapbefine.mapbefine.auth.domain.AuthMember; | ||
import com.mapbefine.mapbefine.member.domain.Member; | ||
import com.mapbefine.mapbefine.member.domain.MemberRepository; | ||
import com.mapbefine.mapbefine.member.domain.Status; | ||
import com.mapbefine.mapbefine.member.exception.MemberErrorCode; | ||
import com.mapbefine.mapbefine.member.exception.MemberException.MemberNotFoundException; | ||
import com.mapbefine.mapbefine.permission.exception.PermissionException.PermissionForbiddenException; | ||
import com.mapbefine.mapbefine.pin.domain.Pin; | ||
import com.mapbefine.mapbefine.pin.domain.PinImageRepository; | ||
import com.mapbefine.mapbefine.pin.domain.PinRepository; | ||
import com.mapbefine.mapbefine.topic.domain.Topic; | ||
import com.mapbefine.mapbefine.topic.domain.TopicRepository; | ||
import com.mapbefine.mapbefine.topic.exception.TopicException; | ||
import java.util.List; | ||
import org.springframework.stereotype.Service; | ||
|
||
@Service | ||
public class AdminCommandService { | ||
|
||
private final MemberRepository memberRepository; | ||
private final TopicRepository topicRepository; | ||
private final PinRepository pinRepository; | ||
private final PinImageRepository pinImageRepository; | ||
|
||
public AdminCommandService( | ||
MemberRepository memberRepository, | ||
TopicRepository topicRepository, | ||
PinRepository pinRepository, | ||
PinImageRepository pinImageRepository | ||
) { | ||
this.memberRepository = memberRepository; | ||
this.topicRepository = topicRepository; | ||
this.pinRepository = pinRepository; | ||
this.pinImageRepository = pinImageRepository; | ||
} | ||
|
||
public void blockMember(AuthMember authMember, Long memberId) { | ||
Member admin = findMemberById(authMember.getMemberId()); | ||
|
||
validateAdminPermission(admin); | ||
|
||
Member member = findMemberById(memberId); | ||
member.updateStatus(Status.BLOCKED); | ||
List<Long> pinIds = extractPinIdsByMember(member); | ||
|
||
topicRepository.deleteAllByMemberId(memberId); | ||
pinRepository.deleteAllByMemberId(memberId); | ||
pinImageRepository.deleteAllByPinIds(pinIds); | ||
} | ||
|
||
private Member findMemberById(Long id) { | ||
return memberRepository.findById(id) | ||
.orElseThrow(() -> new MemberNotFoundException(MemberErrorCode.MEMBER_NOT_FOUND, id)); | ||
} | ||
|
||
private void validateAdminPermission(Member member) { | ||
if (member.isAdmin()) { | ||
return; | ||
} | ||
|
||
throw new PermissionForbiddenException(PERMISSION_FORBIDDEN_BY_NOT_ADMIN); | ||
} | ||
|
||
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. 요 부분도 AdminQueryService 에서 달았단 코멘트와 의견 동일합니다! |
||
private List<Long> extractPinIdsByMember(Member member) { | ||
return member.getCreatedPins() | ||
.stream() | ||
.map(Pin::getId) | ||
.toList(); | ||
} | ||
|
||
public void deleteTopic(AuthMember authMember, Long topicId) { | ||
Member member = findMemberById(authMember.getMemberId()); | ||
|
||
validateAdminPermission(member); | ||
|
||
topicRepository.deleteById(topicId); | ||
} | ||
|
||
public void deleteTopicImage(AuthMember authMember, Long topicId) { | ||
Member member = findMemberById(authMember.getMemberId()); | ||
|
||
validateAdminPermission(member); | ||
|
||
Topic topic = findTopicById(topicId); | ||
topic.removeImage(); | ||
} | ||
|
||
private Topic findTopicById(Long topicId) { | ||
return topicRepository.findById(topicId) | ||
.orElseThrow(() -> new TopicException.TopicNotFoundException(TOPIC_NOT_FOUND, List.of(topicId))); | ||
} | ||
|
||
public void deletePin(AuthMember authMember, Long pinId) { | ||
Member member = findMemberById(authMember.getMemberId()); | ||
|
||
validateAdminPermission(member); | ||
|
||
pinRepository.deleteById(pinId); | ||
} | ||
|
||
public void deletePinImage(AuthMember authMember, Long pinImageId) { | ||
Member member = findMemberById(authMember.getMemberId()); | ||
|
||
validateAdminPermission(member); | ||
|
||
pinImageRepository.deleteById(pinImageId); | ||
} | ||
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
package com.mapbefine.mapbefine.admin.application; | ||
|
||
import com.mapbefine.mapbefine.admin.dto.AdminMemberDetailResponse; | ||
import com.mapbefine.mapbefine.admin.dto.AdminMemberResponse; | ||
import com.mapbefine.mapbefine.auth.domain.AuthMember; | ||
import com.mapbefine.mapbefine.member.domain.Member; | ||
import com.mapbefine.mapbefine.member.domain.MemberRepository; | ||
import com.mapbefine.mapbefine.member.domain.Role; | ||
import com.mapbefine.mapbefine.member.exception.MemberErrorCode; | ||
import com.mapbefine.mapbefine.member.exception.MemberException.MemberNotFoundException; | ||
import com.mapbefine.mapbefine.permission.exception.PermissionErrorCode; | ||
import com.mapbefine.mapbefine.permission.exception.PermissionException.PermissionForbiddenException; | ||
import com.mapbefine.mapbefine.pin.domain.Pin; | ||
import com.mapbefine.mapbefine.topic.domain.Topic; | ||
import java.util.List; | ||
import org.springframework.stereotype.Service; | ||
|
||
@Service | ||
public class AdminQueryService { | ||
|
||
private final MemberRepository memberRepository; | ||
|
||
public AdminQueryService(MemberRepository memberRepository) { | ||
this.memberRepository = memberRepository; | ||
} | ||
|
||
public List<AdminMemberResponse> findAllMemberDetails(AuthMember authMember) { | ||
Member admin = findMemberById(authMember.getMemberId()); | ||
validateAdminPermission(admin); | ||
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. P4. AuthMember 안에 만약 해당 메서드 도입한다면 여기선 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. 위 코멘트와 관련이 있는 것 같아요. 다른 분들의 의견처럼 Interceptor에서 수행하기 때문에, Service에서 검증이 필요 없다고 하시면 기존 코드 그대로 가져가도 될 것 같아요. 내일 이야기 나누어보고 결정하도록 하겠습니다. 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. 해당 사항 반영했습니당 ~! |
||
|
||
List<Member> members = memberRepository.findAllByMemberInfoRole(Role.USER); | ||
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. P5. 전체 사용자가 아닌 USER만 찾는 것 같은데 ADMIN은 어떤 이유에서 제외하셨는지 궁금합니당ㅋㅋ 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. ADMIN이 ADMIN을 삭제할까봐...? 그냥 관리자는 일반 유저들을 관리한다고 생각해서 위와 같이 구현했던 것 같아요. 모든 회원을 조회하도록 수정하는 것이 자연스럽다면, blockMember 메서드에서 삭제하려는 Member가 Admin인지 검증하는 로직이 필요하겠네요. 어떻게 생각하시나용 |
||
|
||
return members.stream() | ||
.map(AdminMemberResponse::from) | ||
.toList(); | ||
} | ||
|
||
private Member findMemberById(Long id) { | ||
return memberRepository.findById(id) | ||
.orElseThrow(() -> new MemberNotFoundException(MemberErrorCode.MEMBER_NOT_FOUND, id)); | ||
} | ||
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. P2. 이 코드 흐름에서 Member를 찾지 못한다면 400번대(사용자 잘못의 오류)보다는 코드나 데이터가 잘못되어서 발생하는 것 아닐까요 ?? (동일한 흐름의 코드들 모두 해당하는 코멘트입니다!) private Member findMemberById(Long id) {
return memberRepository.findById(id)
.orElseThrow(() -> new NoSuchElementException("findCreatorByAuthMember; member not found; id=" + id));
} 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. 이전 PR들에서 해당 부분을 전혀 인지 못했었던 것 같네요. 다만, Interceptor에서 검증을 수행하기 때문에, Server ERROR로 본다는 것은 Service 계층이 Interceptor에 의존적인 것 같다는 생각이 듭니다. 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.
이 부분 확실히 논의해야 할 부분인 것 같네요! 내일 얘기해보아요~ |
||
|
||
private void validateAdminPermission(Member member) { | ||
if (member.isAdmin()) { | ||
return; | ||
} | ||
|
||
throw new PermissionForbiddenException(PermissionErrorCode.PERMISSION_FORBIDDEN_BY_NOT_ADMIN); | ||
} | ||
|
||
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. 다른 분들이 이미 코멘트 달았나 모르긴 하겠지만, 현재 코드에서 Admin 관련 API 에 요청이 오는 경우 AdminAuthInterceptor 가 동작하고 거기에서 validateAdmin 을 진행해주는 걸로 알고 있습니다! 그렇기 때문에 실제 Service 로직에서는 admin 인지 검증하는 것이 불필요하지 않을까용? 제가 잘못생각한 부분이 있는지 쥬니짱이 맘껏 지적해주세용. 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. 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. 어쩔 tv! |
||
public AdminMemberDetailResponse findMemberDetail(AuthMember authMember, Long memberId) { | ||
Member admin = findMemberById(authMember.getMemberId()); | ||
|
||
validateAdminPermission(admin); | ||
|
||
Member findMember = findMemberById(memberId); | ||
List<Topic> topics = findMember.getCreatedTopics(); | ||
List<Pin> pins = findMember.getCreatedPins(); | ||
|
||
return AdminMemberDetailResponse.of(findMember, topics, pins); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
package com.mapbefine.mapbefine.admin.dto; | ||
|
||
import com.mapbefine.mapbefine.member.domain.Member; | ||
import com.mapbefine.mapbefine.member.domain.MemberInfo; | ||
import com.mapbefine.mapbefine.pin.domain.Pin; | ||
import com.mapbefine.mapbefine.pin.dto.response.PinResponse; | ||
import com.mapbefine.mapbefine.topic.domain.Topic; | ||
import com.mapbefine.mapbefine.topic.dto.response.TopicResponse; | ||
import java.time.LocalDateTime; | ||
import java.util.List; | ||
|
||
public record AdminMemberDetailResponse( | ||
Long id, | ||
String nickName, | ||
String email, | ||
String imageUrl, | ||
List<TopicResponse> topics, | ||
List<PinResponse> pins, | ||
LocalDateTime updatedAt | ||
) { | ||
|
||
// TODO: 2023/09/12 topics, pins 모두 member를 통해 얻어올 수 있다. Service에서 꺼내서 넘겨줄 것인가 ? 아니면 DTO에서 꺼내올 것인가 ? | ||
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. 제가 최근들어 N + 1 문제에 대해서 알게되서 그런지, Member 에서 꺼내오는 것이 추후 Join 을 통해서 성능 개선하기에 쉬울 것 같아요. 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. 근데 옆에서 석진씨가 OneToMany 컬럼이 2개 이상일 때 Fetch Join 하면 에러날 수도 있다고 하네요! 다음에 같이 한번 실험해봐요 홍홍ㅎ옿옿옿옿오 |
||
public static AdminMemberDetailResponse of( | ||
Member member, | ||
List<Topic> topics, | ||
List<Pin> pins | ||
) { | ||
MemberInfo memberInfo = member.getMemberInfo(); | ||
List<TopicResponse> topicResponses = topics.stream() | ||
.map(TopicResponse::fromGuestQuery) | ||
.toList(); | ||
List<PinResponse> pinResponses = pins.stream() | ||
.map(PinResponse::from) | ||
.toList(); | ||
|
||
return new AdminMemberDetailResponse( | ||
member.getId(), | ||
memberInfo.getNickName(), | ||
memberInfo.getEmail(), | ||
memberInfo.getImageUrl(), | ||
topicResponses, | ||
pinResponses, | ||
member.getUpdatedAt() | ||
); | ||
} | ||
|
||
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
package com.mapbefine.mapbefine.admin.dto; | ||
|
||
import com.mapbefine.mapbefine.member.domain.Member; | ||
import com.mapbefine.mapbefine.member.domain.MemberInfo; | ||
import java.time.LocalDateTime; | ||
|
||
public record AdminMemberResponse( | ||
Long id, | ||
String nickName, | ||
String email, | ||
String imageUrl, | ||
LocalDateTime updatedAt | ||
) { | ||
|
||
public static AdminMemberResponse from(Member member) { | ||
MemberInfo memberInfo = member.getMemberInfo(); | ||
|
||
return new AdminMemberResponse( | ||
member.getId(), | ||
memberInfo.getNickName(), | ||
memberInfo.getEmail(), | ||
memberInfo.getImageUrl(), | ||
member.getUpdatedAt() | ||
); | ||
} | ||
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
package com.mapbefine.mapbefine.admin.presentation; | ||
|
||
import com.mapbefine.mapbefine.admin.application.AdminCommandService; | ||
import com.mapbefine.mapbefine.admin.application.AdminQueryService; | ||
import com.mapbefine.mapbefine.admin.dto.AdminMemberDetailResponse; | ||
import com.mapbefine.mapbefine.admin.dto.AdminMemberResponse; | ||
import com.mapbefine.mapbefine.auth.domain.AuthMember; | ||
import java.util.List; | ||
import org.springframework.http.ResponseEntity; | ||
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.RequestMapping; | ||
import org.springframework.web.bind.annotation.RestController; | ||
|
||
@RestController | ||
@RequestMapping("/admin") | ||
public class AdminController { | ||
|
||
private final AdminQueryService adminQueryService; | ||
private final AdminCommandService adminCommandService; | ||
|
||
|
||
public AdminController(AdminQueryService adminQueryService, AdminCommandService adminCommandService) { | ||
this.adminQueryService = adminQueryService; | ||
this.adminCommandService = adminCommandService; | ||
} | ||
|
||
@GetMapping("/members") | ||
public ResponseEntity<List<AdminMemberResponse>> findAllMembers(AuthMember authMember) { | ||
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. P3. 이미 관리자가 호출한 게 확인이 되었다면 AuthMember를 아예 안받아도 되지는 않나요?! 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. Service에서 이중으로 검증하기 위함이었어요 ! 어떤 방법이든 Service에서 검증해줄 수는 있으니까요. 어떤 방법이 좋을까요 ? 도이뿐만 아니라, 준팍과 매튜도 동일한 내용에 대해서 코멘트 남겨주셔서 의견 덧붙입니다. 서비스가 핵심 비즈니스 로직을 담고 있는 만큼, 서비스에서의 검증은 필수적이라고 생각했어요. 혹여나, 다른 Controller에서 해당 Service를 호출하게 된다면, 권한과 상관없이 관리자 기능을 수행할수도 있지 않을까요 ? 관리 포인트가 늘어나게 된다는 점에서 동일한 리뷰를 주신 것 같은데요. 저는 Interceptor가 중복 코드를 없애기 위해서, AOP를 통해 Admin관련 서비스 메서드들이 호출되기 이전에 매번 검증 메서드를 호출하도록 하는 방법이 있을 것 같아요. 다만, Admin만을 위해 AOP를 도입하는 것이 맞을까 라는 의문이 들기도 하네요. 내일 오전 강의 시작 전에(혹은 오후에) 잠깐 모여서 이야기 나누어봤으면 좋겠습니다. |
||
List<AdminMemberResponse> responses = adminQueryService.findAllMemberDetails(authMember); | ||
|
||
return ResponseEntity.ok(responses); | ||
} | ||
|
||
@DeleteMapping("/members/{memberId}") | ||
public ResponseEntity<Void> deleteMember(AuthMember authMember, @PathVariable Long memberId) { | ||
adminCommandService.blockMember(authMember, memberId); | ||
|
||
return ResponseEntity.noContent().build(); | ||
} | ||
|
||
@GetMapping("/members/{memberId}") | ||
public ResponseEntity<AdminMemberDetailResponse> findMember(AuthMember authMember, @PathVariable Long memberId) { | ||
AdminMemberDetailResponse response = adminQueryService.findMemberDetail(authMember, memberId); | ||
|
||
return ResponseEntity.ok(response); | ||
} | ||
|
||
@DeleteMapping("/topics/{topicId}") | ||
public ResponseEntity<Void> deleteTopic(AuthMember authMember, @PathVariable Long topicId) { | ||
adminCommandService.deleteTopic(authMember, topicId); | ||
|
||
return ResponseEntity.noContent().build(); | ||
} | ||
|
||
@DeleteMapping("/topics/{topicId}/images") | ||
public ResponseEntity<Void> deleteTopicImage(AuthMember authMember, @PathVariable Long topicId) { | ||
adminCommandService.deleteTopicImage(authMember, topicId); | ||
|
||
return ResponseEntity.noContent().build(); | ||
} | ||
|
||
@DeleteMapping("/pins/{pinId}") | ||
public ResponseEntity<Void> deletePin(AuthMember authMember, @PathVariable Long pinId) { | ||
adminCommandService.deletePin(authMember, pinId); | ||
|
||
return ResponseEntity.noContent().build(); | ||
} | ||
|
||
@DeleteMapping("/pins/images/{imageId}") | ||
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. P2. deleteTopicImage와 같이 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.
차라리 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. 전 이 부분은 쥬니가 한 게 더 자연스럽다구 생각합니다. Pins 다음에 PinId가 들어가면 의미가 더 명확해지긴 하겠지만 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. 오 쥬니 새로운 의견대로 가는 게 제일 깔끔하겠는데요? 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. 아 이부분은 제가 생각을 잘못한 것 같아요!!! 쥬니가 하신대로 진행하는 것 동의합니다 ~ |
||
public ResponseEntity<Void> deletePinImage(AuthMember authMember, @PathVariable Long imageId) { | ||
adminCommandService.deletePinImage(authMember, imageId); | ||
|
||
return ResponseEntity.noContent().build(); | ||
} | ||
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,6 +5,8 @@ | |
import com.mapbefine.mapbefine.auth.domain.member.User; | ||
import com.mapbefine.mapbefine.member.domain.Member; | ||
import com.mapbefine.mapbefine.member.domain.MemberRepository; | ||
import com.mapbefine.mapbefine.member.exception.MemberErrorCode; | ||
import com.mapbefine.mapbefine.member.exception.MemberException.MemberNotFoundException; | ||
import com.mapbefine.mapbefine.topic.domain.Topic; | ||
import java.util.List; | ||
import java.util.Objects; | ||
|
@@ -60,4 +62,18 @@ private List<Long> getCreatedTopics(Member member) { | |
.toList(); | ||
} | ||
|
||
public boolean isAdmin(Long memberId) { | ||
if (Objects.isNull(memberId)) { | ||
return false; | ||
} | ||
|
||
Member member = findMember(memberId); | ||
|
||
return member.isAdmin(); | ||
} | ||
|
||
private Member findMember(Long memberId) { | ||
return memberRepository.findById(memberId) | ||
.orElseThrow(() -> new MemberNotFoundException(MemberErrorCode.MEMBER_NOT_FOUND, memberId)); | ||
} | ||
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. P2. 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. 차라리 validateRole 자체를 AuthService에 두는 건 어떨가요? 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. 아래와 같이 수정하였습니다 ! public boolean isAdmin(Long memberId) {
if (Objects.isNull(memberId)) {
return false;
}
Optional<Member> member = memberRepository.findById(memberId);
return member.map(Member::isAdmin)
.orElse(false);
} |
||
} |
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.
S3 연동되면 또 생각해야 하는게 많아지려나요.. 후후..
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.
그리고 Permission 과 Bookmark, Atlas 등등은 안지워도 될까요?
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.
사실 Permission, Bookmark 해야되는거 알고 있는데, 귀찮아서요 ...
너무 많은 Repository를 알고 있어요......
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.
그쵸 사실 굉장히 귀찮은 것 같아요.. 이 부분은 추후에 의논을 통해서 해결해볼까요?