Skip to content
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

✨ feat: 최근 조회한 공고 기능 구현 #152

Merged
merged 10 commits into from
Feb 10, 2024
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ public Authentication attemptAuthentication(
String password = (String)requestBody.get("password");
String fcmToken = (String)requestBody.get("fcmToken");

redisUtil.save(
redisUtil.saveAsValue(
email + "_fcm_token",
fcmToken,
999999999L,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public void logout(HttpServletRequest request, HttpServletResponse response, Aut

String accessToken = jwtUtil.resolveAccessToken(request);

redisUtil.save(
redisUtil.saveAsValue(
accessToken,
"logout",
jwtUtil.getExpTime(accessToken),
Expand All @@ -40,7 +40,7 @@ public void logout(HttpServletRequest request, HttpServletResponse response, Aut
String email = jwtUtil.getEmail(accessToken);

redisUtil.delete(
email
email + "_refresh_token"
);

redisUtil.delete(
Expand Down
8 changes: 4 additions & 4 deletions src/main/java/com/sponus/sponusbe/auth/jwt/util/JwtUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -83,8 +83,8 @@ public String createJwtRefreshToken(CustomUserDetails customUserDetails) {
.signWith(secretKey)
.compact();

redisUtil.save(
customUserDetails.getEmail(),
redisUtil.saveAsValue(
customUserDetails.getEmail() + "_refresh_token",
refreshToken,
refreshExpMs,
TimeUnit.MILLISECONDS
Expand All @@ -94,7 +94,7 @@ public String createJwtRefreshToken(CustomUserDetails customUserDetails) {
}

public JwtPair reissueToken(String refreshToken) {
// TODO: 임시메서드(작동안함). Repository에 대한 의존성을 가져야해서 Service로 빼야함

CustomUserDetails tempCustomUserDetails = new CustomUserDetails(
getId(refreshToken),
getEmail(refreshToken),
Expand Down Expand Up @@ -125,7 +125,7 @@ public void validateRefreshToken(String refreshToken) {
String email = getEmail(refreshToken);

//redis에 refreshToken 있는지 검증
if (!redisUtil.hasKey(email)) {
if (!redisUtil.hasKey(email + "_refresh_token")) {
log.warn("[*] case : Invalid refreshToken");
throw new SecurityCustomException(SecurityErrorCode.INVALID_TOKEN);
}
Expand Down
27 changes: 26 additions & 1 deletion src/main/java/com/sponus/sponusbe/auth/jwt/util/RedisUtil.java
Original file line number Diff line number Diff line change
@@ -1,22 +1,43 @@
package com.sponus.sponusbe.auth.jwt.util;

import java.util.List;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

@Component
@Slf4j
@RequiredArgsConstructor
public class RedisUtil {

private final RedisTemplate<String, Object> redisTemplate;

public void save(String key, Object val, Long time, TimeUnit timeUnit) {
public void saveAsValue(String key, Object val, Long time, TimeUnit timeUnit) {
redisTemplate.opsForValue().set(key, val, time, timeUnit);
}

public void appendToRecentlyViewedAnnouncement(String key, String newValue) {
long RECENT_VIEWED_ANNOUNCEMENT_LIMIT = 20;

log.info("[*] Newly Viewed Announcement: " + newValue);
Object mostRecentlyViewedValue = redisTemplate.opsForList().index(key, 0);
if (Objects.equals(mostRecentlyViewedValue, newValue)) {
log.info("[*] Skip saving viewed history...");
return;
}
if (Objects.equals(redisTemplate.opsForList().size(key), RECENT_VIEWED_ANNOUNCEMENT_LIMIT)) {
log.info("[*] Recent Announcement Deque Full Capacity..");
log.info("[*] Del Top()");
redisTemplate.opsForList().rightPop(key);
}
redisTemplate.opsForList().leftPush(key, newValue);
}

public boolean hasKey(String key) {
return Boolean.TRUE.equals(redisTemplate.hasKey(key));
}
Expand All @@ -25,6 +46,10 @@ public Object get(String key) {
return redisTemplate.opsForValue().get(key);
}

public List<Object> getList(String key) {
return redisTemplate.opsForList().range(key, 0, -1);
}

public boolean delete(String key) {
return Boolean.TRUE.equals(redisTemplate.delete(key));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,11 @@ public ApiResponse<Void> getAnnouncement() {
}

@GetMapping("/{announcementId}")
public ApiResponse<AnnouncementDetailResponse> getAnnouncement(@PathVariable Long announcementId) {
return ApiResponse.onSuccess(announcementService.getAnnouncement(announcementId));
public ApiResponse<AnnouncementDetailResponse> getAnnouncement(
@PathVariable Long announcementId,
@AuthOrganization Organization authOrganization
) {
return ApiResponse.onSuccess(announcementService.getAnnouncement(authOrganization, announcementId));
}

@GetMapping("/status")
Expand Down Expand Up @@ -114,4 +117,13 @@ public ApiResponse<List<AnnouncementSummaryResponse>> getAnnouncementByCategory(
return ApiResponse.onSuccess(
announcementQueryService.getAnnouncementByCategory(category, type));
}

@GetMapping("/recently_viewed_announcements")
public ApiResponse<List<Object>> getRecentAnnouncement(
@AuthOrganization Organization authOrganization
) {
return ApiResponse.onSuccess(
announcementQueryService.getRecentlyViewedAnnouncement(authOrganization)
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,12 @@
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.sponus.sponusbe.auth.jwt.util.RedisUtil;
import com.sponus.sponusbe.domain.announcement.dto.response.AnnouncementSummaryResponse;
import com.sponus.sponusbe.domain.announcement.entity.enums.AnnouncementCategory;
import com.sponus.sponusbe.domain.announcement.entity.enums.AnnouncementType;
import com.sponus.sponusbe.domain.announcement.repository.AnnouncementRepository;
import com.sponus.sponusbe.domain.organization.entity.Organization;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
Expand All @@ -20,6 +22,7 @@
public class AnnouncementQueryService {

private final AnnouncementRepository announcementRepository;
private final RedisUtil redisUtil;

public List<AnnouncementSummaryResponse> searchAnnouncement(String keyword) {
log.info("search announcement by keyword: {}", keyword);
Expand Down Expand Up @@ -57,4 +60,8 @@ else if (type != null) {
return announcementRepository.findAll().stream().map(AnnouncementSummaryResponse::from).toList();
}
}

public List<Object> getRecentlyViewedAnnouncement(Organization authOrganization) {
return redisUtil.getList(authOrganization.getEmail() + "_recently_viewed_list");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import com.sponus.sponusbe.auth.jwt.util.RedisUtil;
import com.sponus.sponusbe.domain.announcement.dto.request.AnnouncementCreateRequest;
import com.sponus.sponusbe.domain.announcement.dto.request.AnnouncementUpdateRequest;
import com.sponus.sponusbe.domain.announcement.dto.response.AnnouncementCreateResponse;
Expand All @@ -32,6 +33,7 @@ public class AnnouncementService {

private final AnnouncementRepository announcementRepository;
private final S3Service s3Service;
private final RedisUtil redisUtil;

public AnnouncementCreateResponse createAnnouncement(
Organization authOrganization,
Expand All @@ -43,10 +45,14 @@ public AnnouncementCreateResponse createAnnouncement(
return AnnouncementCreateResponse.from(announcementRepository.save(announcement));
}

public AnnouncementDetailResponse getAnnouncement(Long announcementId) {
public AnnouncementDetailResponse getAnnouncement(Organization organization, Long announcementId) {
Announcement announcement = announcementRepository.findById(announcementId)
.orElseThrow(() -> new AnnouncementException(AnnouncementErrorCode.ANNOUNCEMENT_NOT_FOUND));
announcement.increaseViewCount();

redisUtil.appendToRecentlyViewedAnnouncement(organization.getEmail() + "_recently_viewed_list",
String.valueOf(announcementId));

return AnnouncementDetailResponse.from(announcement);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,13 @@ public class Bookmark extends BaseEntity {
@JoinColumn(name = "announcement_id", foreignKey = @ForeignKey(ConstraintMode.NO_CONSTRAINT))
private Announcement announcement;

public void increaseSaveCount() { this.saveCount++; }
public void increaseSaveCount() {
this.saveCount++;
}

public void decreaseSaveCount() {
if (this.saveCount > 0) {
this.saveCount--;
} }
this.saveCount--;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,4 @@ public interface BookmarkRepository extends JpaRepository<Bookmark, Long> {
List<Bookmark> findByOrganizationOrderByCreatedAtDesc(Organization organization);
List<Bookmark> findByOrganizationOrderBySaveCountDesc(Organization organization);

}

}
Original file line number Diff line number Diff line change
Expand Up @@ -60,4 +60,4 @@ public List<BookmarkGetResponse> getSavedBookmark(Organization organization) {
.map(bookmark -> BookmarkGetResponse.from(bookmark.getAnnouncement(), bookmark))
.collect(Collectors.toList());
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.sponus.sponusbe.domain.organizationLink.dto.request.OrganizationLinkUpdateRequest;
import com.sponus.sponusbe.domain.organizationLink.dto.response.OrganizationLinkGetResponse;

import org.springframework.web.bind.annotation.*;

import com.sponus.sponusbe.auth.annotation.AuthOrganization;
Expand Down Expand Up @@ -30,13 +31,14 @@ public ApiResponse<OrganizationLinkCreateResponse> createOrganizationLink(
}

@GetMapping("/{organizationLinkId}")
public ApiResponse<OrganizationLinkGetResponse> getOrganizationLink(@PathVariable("organizationLinkId") Long organizationLinkId) {
public ApiResponse<OrganizationLinkGetResponse> getOrganizationLink(
@PathVariable("organizationLinkId") Long organizationLinkId) {
return ApiResponse.onSuccess(organizationLinkQueryService.getOrganizationLink(organizationLinkId));
}

@PatchMapping("/{organizationLinkId}")
public ApiResponse<Void> updateOrganizationLink(@PathVariable("organizationLinkId") Long organizationLinkId,
@RequestBody OrganizationLinkUpdateRequest request) {
@RequestBody OrganizationLinkUpdateRequest request) {
organizationLinkService.updateOrganizationLink(organizationLinkId, request);
return ApiResponse.onSuccess(null);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package com.sponus.sponusbe.domain.organizationLink.dto.request;

public record OrganizationLinkUpdateRequest(
String name,
String url
String name,
String url
) {
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import com.sponus.sponusbe.domain.organization.entity.Organization;

import com.sponus.sponusbe.domain.organizationLink.dto.request.OrganizationLinkUpdateRequest;

import jakarta.persistence.Column;
import jakarta.persistence.ConstraintMode;
import jakarta.persistence.Entity;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import com.sponus.sponusbe.domain.organizationLink.dto.response.OrganizationLinkGetResponse;
import com.sponus.sponusbe.domain.organizationLink.entity.OrganizationLink;
import com.sponus.sponusbe.domain.organizationLink.repository.OrganizationLinkRepository;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

Expand All @@ -15,12 +16,13 @@
@Transactional(readOnly = true)
@Service
public class OrganizationLinkQueryService {
private final OrganizationLinkRepository organizationLinkRepository;
public OrganizationLinkGetResponse getOrganizationLink(Long organizationLinkId) {
OrganizationLink organizationLink = organizationLinkRepository.findById(organizationLinkId)
.orElseThrow(() -> new OrganizationException(ORGANIZATION_LINK_NOT_FOUND));
private final OrganizationLinkRepository organizationLinkRepository;

public OrganizationLinkGetResponse getOrganizationLink(Long organizationLinkId) {
OrganizationLink organizationLink = organizationLinkRepository.findById(organizationLinkId)
.orElseThrow(() -> new OrganizationException(ORGANIZATION_LINK_NOT_FOUND));

return OrganizationLinkGetResponse.from(organizationLink);
return OrganizationLinkGetResponse.from(organizationLink);

}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -56,11 +56,11 @@ public ApiResponse<ReportUpdateResponse> updateReport(
@RequestPart(value = "attachments") List<MultipartFile> attachments) {
return ApiResponse.onSuccess(
reportService.updateReport(
authOrganization,
reportId,
request,
images,
attachments));
authOrganization,
reportId,
request,
images,
attachments));
}

@GetMapping("/{reportId}")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,6 @@ public ReportUpdateResponse updateReport(
if (!isOrganizationsReport(authOrganization.getId(), report))
throw new ReportException(ReportErrorCode.INVALID_ORGANIZATION);


report.update(request.title(), request.content());
setReportImages(images, report);
setReportAttachments(attachments, report);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,21 +36,21 @@ public ApiResponse<TagCreateResponse> createTag(@AuthOrganization Organization o
return ApiResponse.onSuccess(tagService.createTag(organization.getId(), request));
}

@DeleteMapping("/{tagId}")
@DeleteMapping("/{tagId}")
public ApiResponse<Void> deleteTag(@PathVariable Long tagId) {
tagService.deleteTag(tagId);
return ApiResponse.onSuccess(null);
}

@PatchMapping("/{tagId}")
@PatchMapping("/{tagId}")
public ApiResponse<Void> updateTag(@PathVariable Long tagId, @RequestBody TagUpdateRequest request) {
tagService.updateTag(tagId, request);
return ApiResponse.onSuccess(null);
}
@GetMapping("/{tagId}")

@GetMapping("/{tagId}")
public ApiResponse<TagGetResponse> getTag(@PathVariable Long tagId) {
return ApiResponse.onSuccess(tagQueryService.getTag(tagId));
}

}
Loading