Skip to content

Commit

Permalink
[Feat/#178] add controller related recommend sync & init and set secu…
Browse files Browse the repository at this point in the history
…rity config
  • Loading branch information
Han-Jeong committed Apr 3, 2024
1 parent 3b2ab4f commit 16f7212
Show file tree
Hide file tree
Showing 14 changed files with 82 additions and 101 deletions.
2 changes: 0 additions & 2 deletions src/main/java/com/example/waggle/WaggleApplication.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,13 @@
import com.example.waggle.global.util.SecurityUtil;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.data.domain.AuditorAware;
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
import org.springframework.scheduling.annotation.EnableScheduling;

import java.util.Optional;

@EnableCaching
@EnableScheduling
@EnableJpaAuditing
@SpringBootApplication
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@ public void initRecommend(Long memberId) {
ValueOperations<String, String> values = redisTemplate.opsForValue();
String key = initKeyPrefix + memberId;
values.set(key, "initRecommend");
SetOperations<String, String> setOperations = redisTemplate.opsForSet();
String memberKey = recommendMemberKeyPrefix + memberId;
setOperations.add(memberKey, String.valueOf(0L));
}

public boolean existInitRecommend(Long memberId) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,14 +46,16 @@ private void validateInitRecommend(Member member) {
}
}

@Scheduled(fixedRate = 1000 * 60 * 3L)
@Scheduled(fixedRate = 1000 * 60 * 60 * 3L)
// @Scheduled(fixedRate = 1000 * 60 * 3L)
@Override
public void syncRecommendation() {
redisService.getAllRecommendingMemberList().stream()
.map(memberRepository::findById)
.filter(Optional::isPresent)
.map(Optional::get)
.forEach(member -> {
recommendRepository.deleteAllByMember(member);
redisService.getRecommendedBoardList(member.getId()).stream()
.map(boardRepository::findById)
.filter(Optional::isPresent)
Expand Down

This file was deleted.

22 changes: 16 additions & 6 deletions src/main/java/com/example/waggle/global/config/SecurityConfig.java
Original file line number Diff line number Diff line change
@@ -1,16 +1,13 @@
package com.example.waggle.global.config;


import static org.springframework.security.web.util.matcher.AntPathRequestMatcher.antMatcher;

import com.example.waggle.global.security.exception.JwtAccessDeniedHandler;
import com.example.waggle.global.security.exception.JwtAuthenticationEntryPoint;
import com.example.waggle.global.security.filter.JwtAuthenticationFilter;
import com.example.waggle.global.security.filter.JwtExceptionFilter;
import com.example.waggle.global.security.oauth2.CustomOAuth2UserService;
import com.example.waggle.global.security.oauth2.handler.OAuth2AuthenticationFailureHandler;
import com.example.waggle.global.security.oauth2.handler.OAuth2AuthenticationSuccessHandler;
import java.util.List;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
Expand All @@ -23,6 +20,10 @@
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.util.matcher.RequestMatcher;

import java.util.List;

import static org.springframework.security.web.util.matcher.AntPathRequestMatcher.antMatcher;

@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
@RequiredArgsConstructor
@Configuration
Expand Down Expand Up @@ -83,7 +84,7 @@ private void configureAuth(HttpSecurity httpSecurity) throws Exception {
.requestMatchers(authorizationDormant()).hasRole("DORMANT")
.requestMatchers(authorizationGuest()).hasRole("GUEST")
.requestMatchers(authorizationUser()).hasRole("USER")
// .requestMatchers(authenticatedEndpoints()).authenticated()
.requestMatchers(authenticatedEndpoints()).authenticated()
//정적 페이지 허가
.requestMatchers("/", "/.well-known/**", "/css/**", "/*.ico", "/error", "/images/**")
.permitAll() // 임시로 모든 API 허용
Expand Down Expand Up @@ -116,6 +117,14 @@ private RequestMatcher[] additionalSwaggerRequests() {
return requestMatchers.toArray(RequestMatcher[]::new);
}

private RequestMatcher[] authenticatedEndpoints() {
List<RequestMatcher> requestMatchers = List.of(
antMatcher("api/recommends/init"),
antMatcher(HttpMethod.GET, "api/recommends/")
);
return requestMatchers.toArray(RequestMatcher[]::new);
}

private RequestMatcher[] authRelatedEndpoints() {
List<RequestMatcher> requestMatchers = List.of(
antMatcher("/oauth2/**"),
Expand All @@ -141,7 +150,7 @@ private RequestMatcher[] permitAllRequest() {
antMatcher(HttpMethod.GET, "/api/stories/**"),
antMatcher(HttpMethod.GET, "/api/questions/**"),
antMatcher(HttpMethod.GET, "/api/sirens/**"),
antMatcher(HttpMethod.GET, "/api/recommends/**"),
antMatcher(HttpMethod.GET, "/api/recommends/{boardId}/memberList"),
antMatcher(HttpMethod.GET, "/api/answers/**"),
antMatcher(HttpMethod.GET, "/api/follows/**"),
antMatcher("/api/media/**")
Expand All @@ -151,7 +160,8 @@ private RequestMatcher[] permitAllRequest() {

private RequestMatcher[] authorizationAdmin() {
List<RequestMatcher> requestMatchers = List.of(
antMatcher(HttpMethod.DELETE, "/api/members/{memberId}/force")
antMatcher(HttpMethod.DELETE, "/api/members/{memberId}/force"),
antMatcher(HttpMethod.GET, "api/recommends/sync")
);
return requestMatchers.toArray(RequestMatcher[]::new);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
import com.example.waggle.global.annotation.auth.AuthUser;
import com.example.waggle.global.payload.ApiResponseDto;
import com.example.waggle.global.payload.code.ErrorStatus;
import com.example.waggle.global.util.SecurityUtil;
import com.example.waggle.web.converter.AnswerConverter;
import com.example.waggle.web.dto.answer.AnswerRequest;
import com.example.waggle.web.dto.answer.AnswerResponse.AnswerListDto;
Expand Down Expand Up @@ -73,7 +72,7 @@ public ApiResponseDto<AnswerListDto> getAllAnswerByPage(@PathVariable("questionI
Page<Answer> pagedAnswers = answerQueryService.getPagedAnswers(questionId, pageable);
AnswerListDto listDto = AnswerConverter.toAnswerListDto(pagedAnswers);
//recommend relation field
setRecommendInList(listDto);

return ApiResponseDto.onSuccess(listDto);
}

Expand All @@ -87,7 +86,6 @@ public ApiResponseDto<AnswerListDto> getAnswerByMemberId(@PathVariable("memberId
Pageable pageable = PageRequest.of(currentPage, 10, latestSorting);
Page<Answer> pagedAnswerByUsername = answerQueryService.getPagedAnswerByMemberId(memberId, pageable);
AnswerListDto listDto = AnswerConverter.toAnswerListDto(pagedAnswerByUsername);
setRecommendInList(listDto);
return ApiResponseDto.onSuccess(listDto);
}

Expand All @@ -101,14 +99,4 @@ public ApiResponseDto<Boolean> deleteAnswer(@PathVariable("answerId") Long answe
answerCommandService.deleteAnswer(answerId, member);
return ApiResponseDto.onSuccess(Boolean.TRUE);
}

private void setRecommendInList(AnswerListDto listDto) {
listDto.getAnswerList()
.forEach(answer ->
answer.setRecommendationInfo(
recommendQueryService.getRecommendationInfo(
answer.getBoardId(),
SecurityUtil.getCurrentUsername()))
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
import com.example.waggle.global.payload.ApiResponseDto;
import com.example.waggle.global.payload.code.ErrorStatus;
import com.example.waggle.global.util.MediaUtil;
import com.example.waggle.global.util.SecurityUtil;
import com.example.waggle.web.converter.QuestionConverter;
import com.example.waggle.web.dto.question.QuestionRequest;
import com.example.waggle.web.dto.question.QuestionResponse.QuestionSummaryDto;
Expand Down Expand Up @@ -99,7 +98,7 @@ public ApiResponseDto<QuestionSummaryListDto> getAllQuestions(
Pageable pageable = PageRequest.of(currentPage, 10, latestSorting);
Page<Question> questions = questionQueryService.getPagedQuestions(pageable);
QuestionSummaryListDto listDto = QuestionConverter.toListDto(questions);
setRecommendInList(listDto.getQuestionList());
setRecommendCntInList(listDto.getQuestionList());
return ApiResponseDto.onSuccess(listDto);
}

Expand All @@ -110,7 +109,7 @@ public ApiResponseDto<RepresentativeQuestionDto> getRepresentativeQuestionList()
List<Question> representativeQuestionList = questionQueryService.getRepresentativeQuestionList();
RepresentativeQuestionDto listDto = QuestionConverter.toRepresentativeQuestionDto(
representativeQuestionList);
setRecommendInList(listDto.getQuestionList());
setRecommendCntInList(listDto.getQuestionList());
return ApiResponseDto.onSuccess(listDto);
}

Expand All @@ -124,7 +123,7 @@ public ApiResponseDto<QuestionSummaryListDto> getQuestionsByUsername(@PathVariab
Pageable pageable = PageRequest.of(currentPage, 10, latestSorting);
Page<Question> questions = questionQueryService.getPagedQuestionByMemberId(memberId, pageable);
QuestionSummaryListDto listDto = QuestionConverter.toListDto(questions);
setRecommendInList(listDto.getQuestionList());
setRecommendCntInList(listDto.getQuestionList());
return ApiResponseDto.onSuccess(listDto);
}

Expand All @@ -138,10 +137,7 @@ public ApiResponseDto<QuestionDetailDto> getQuestionByBoardId(
questionCommandService.increaseQuestionViewCount(questionId);
Question questionByBoardId = questionQueryService.getQuestionByBoardId(questionId);
QuestionDetailDto detailDto = QuestionConverter.toDetailDto(questionByBoardId);
detailDto.setRecommendationInfo(recommendQueryService.getRecommendationInfo(
questionId,
SecurityUtil.getCurrentUsername())
);
detailDto.setRecommendCount(recommendQueryService.countRecommend(questionId));
return ApiResponseDto.onSuccess(detailDto);
}

Expand All @@ -157,14 +153,12 @@ public ApiResponseDto<Boolean> deleteQuestion(@PathVariable("questionId") Long q
return ApiResponseDto.onSuccess(Boolean.TRUE);
}

private void setRecommendInList(List<QuestionSummaryDto> questionList) {
private void setRecommendCntInList(List<QuestionSummaryDto> questionList) {
questionList
.forEach(question ->
question.setRecommendationInfo(
recommendQueryService.getRecommendationInfo(
question.getBoardId(),
SecurityUtil.getCurrentUsername()))
);
question.setRecommendCount(
recommendQueryService.countRecommend(question.getBoardId()
)));
}

// TODO 사용자가 작성한 대답과 관련된 question list 가져오기
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import com.example.waggle.domain.member.entity.Member;
import com.example.waggle.domain.recommend.service.RecommendCommandService;
import com.example.waggle.domain.recommend.service.RecommendQueryService;
import com.example.waggle.domain.recommend.service.RecommendSyncService;
import com.example.waggle.global.annotation.ApiErrorCodeExample;
import com.example.waggle.global.annotation.auth.AuthUser;
import com.example.waggle.global.payload.ApiResponseDto;
Expand All @@ -12,14 +13,11 @@
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.tags.Tag;
import java.util.List;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
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 org.springframework.web.bind.annotation.*;

import java.util.List;

@Slf4j
@RequiredArgsConstructor
Expand All @@ -30,13 +28,14 @@
public class RecommendApiController {
private final RecommendCommandService recommendCommandService;
private final RecommendQueryService recommendQueryService;
private final RecommendSyncService recommendSyncService;

@Operation(summary = "게시글 좋아요 혹은 취소 🔑", description = "사용자가 좋아요 버튼을 누릅니다(추가 혹은 취소). 게시글의 좋아요 수가 추가되거나 감소됩니다.")
@ApiErrorCodeExample({
ErrorStatus._INTERNAL_SERVER_ERROR
})
@PostMapping("/{boardId}")
public ApiResponseDto<Long> recommendStory(@PathVariable("boardId") Long boardId,
public ApiResponseDto<Long> recommendBoard(@PathVariable("boardId") Long boardId,
@AuthUser Member member) {
recommendCommandService.handleRecommendation(boardId, member);
return ApiResponseDto.onSuccess(boardId);
Expand All @@ -46,9 +45,39 @@ public ApiResponseDto<Long> recommendStory(@PathVariable("boardId") Long boardId
@ApiErrorCodeExample({
ErrorStatus._INTERNAL_SERVER_ERROR
})
@GetMapping("/{boardId}")
@GetMapping("/{boardId}/memberList")
public ApiResponseDto<MemberSummaryListDto> getRecommendingMembers(@PathVariable("boardId") Long boardId) {
List<Member> recommendingMembers = recommendQueryService.getRecommendingMembers(boardId);
return ApiResponseDto.onSuccess(MemberConverter.toMemberListDto(recommendingMembers));
}

@Operation(summary = "로그인 유저의 게시글 좋아요 유무 확인 🔑", description = "로그인 유저가 해당 게시글에 좋아요를 눌렀는지 확인합니다.")
@ApiErrorCodeExample({
ErrorStatus._INTERNAL_SERVER_ERROR
})
@GetMapping("/{boardId}")
public ApiResponseDto<Boolean> getIsRecommend(@PathVariable("boardId") Long boardId,
@AuthUser Member member) {
return ApiResponseDto.onSuccess(recommendQueryService.checkRecommend(boardId, member.getUsername()));
}

@Operation(summary = "로그인 유저 데이터베이스 -> 캐시 동기화 🔑", description = "유저의 활동을 위해 좋아요 정보를 rdb -> redis 로 옮깁니다.")
@ApiErrorCodeExample({
ErrorStatus._INTERNAL_SERVER_ERROR
})
@GetMapping("/init")
public ApiResponseDto<Long> initRecommendInfoInRedis(@AuthUser Member member) {
recommendSyncService.initRecommendationInRedis(member);
return ApiResponseDto.onSuccess(member.getId());
}

@Operation(summary = "캐시 -> 데이터베이스 동기화 🔑", description = "유저의 활동을 위해 좋아요 정보를 rdb -> redis 로 옮깁니다.")
@ApiErrorCodeExample({
ErrorStatus._INTERNAL_SERVER_ERROR
})
@GetMapping("/sync")
public ApiResponseDto<Boolean> syncRecommendInfo() {
recommendSyncService.syncRecommendation();
return ApiResponseDto.onSuccess(true);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
import com.example.waggle.global.payload.ApiResponseDto;
import com.example.waggle.global.payload.code.ErrorStatus;
import com.example.waggle.global.util.MediaUtil;
import com.example.waggle.global.util.SecurityUtil;
import com.example.waggle.web.converter.SirenConverter;
import com.example.waggle.web.dto.siren.SirenRequest;
import com.example.waggle.web.dto.siren.SirenResponse.RepresentativeSirenDto;
Expand Down Expand Up @@ -98,7 +97,7 @@ public ApiResponseDto<SirenListDto> getAllSiren(
Pageable pageable = PageRequest.of(currentPage, 10, latestSorting);
Page<Siren> pagedSirenList = sirenQueryService.getPagedSirenList(pageable);
SirenListDto listDto = SirenConverter.toSirenListDto(pagedSirenList);
setRecommendInList(listDto.getSirenList());
setRecommendCntInList(listDto.getSirenList());
return ApiResponseDto.onSuccess(listDto);
}

Expand All @@ -109,7 +108,7 @@ public ApiResponseDto<RepresentativeSirenDto> getRepresentativeSirenList() {
List<Siren> representativeSirenList = sirenQueryService.getRepresentativeSirenList();
RepresentativeSirenDto listDto = SirenConverter.toRepresentativeSirenDto(
representativeSirenList);
setRecommendInList(listDto.getSirenList());
setRecommendCntInList(listDto.getSirenList());
return ApiResponseDto.onSuccess(listDto);
}

Expand All @@ -123,7 +122,7 @@ public ApiResponseDto<SirenListDto> getSirenListByUsername(@PathVariable("member
Pageable pageable = PageRequest.of(currentPage, 10, latestSorting);
Page<Siren> pagedSirenList = sirenQueryService.getPagedSirenListByMemberId(memberId, pageable);
SirenListDto listDto = SirenConverter.toSirenListDto(pagedSirenList);
setRecommendInList(listDto.getSirenList());
setRecommendCntInList(listDto.getSirenList());
return ApiResponseDto.onSuccess(listDto);
}

Expand All @@ -136,10 +135,7 @@ public ApiResponseDto<SirenDetailDto> getSirenByBoardId(@PathVariable("sirenId")
sirenCommandService.increaseSirenViewCount(sirenId);
Siren siren = sirenQueryService.getSirenByBoardId(sirenId);
SirenDetailDto detailDto = SirenConverter.toSirenDetailDto(siren);
detailDto.setRecommendationInfo(recommendQueryService.getRecommendationInfo(
sirenId,
SecurityUtil.getCurrentUsername()
));
detailDto.setRecommendCount(recommendQueryService.countRecommend(sirenId));

return ApiResponseDto.onSuccess(detailDto);
}
Expand All @@ -155,13 +151,11 @@ public ApiResponseDto<Boolean> deleteSiren(@PathVariable("sirenId") Long sirenId
return ApiResponseDto.onSuccess(Boolean.TRUE);
}

private void setRecommendInList(List<SirenSummaryDto> sirenList) {
private void setRecommendCntInList(List<SirenSummaryDto> sirenList) {
sirenList
.forEach(siren ->
siren.setRecommendationInfo(
recommendQueryService.getRecommendationInfo(
siren.getBoardId(),
SecurityUtil.getCurrentUsername()))
siren.setRecommendCount(
recommendQueryService.countRecommend(siren.getBoardId()))
);
}
}
Loading

0 comments on commit 16f7212

Please sign in to comment.