Skip to content

Commit

Permalink
[fix] conflict 해결 - #61
Browse files Browse the repository at this point in the history
# Conflicts:
#	dateroad-api/src/main/java/org/dateroad/user/api/UserController.java
#	dateroad-api/src/main/java/org/dateroad/user/service/UserService.java
#	dateroad-domain/src/main/java/org/dateroad/tag/repository/UserTagRepository.java
  • Loading branch information
sjk4618 committed Jul 12, 2024
2 parents 179c7bd + 1431634 commit 9e2bc41
Show file tree
Hide file tree
Showing 64 changed files with 1,559 additions and 157 deletions.
1 change: 1 addition & 0 deletions dateroad-api/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'org.springframework.boot:spring-boot-starter-data-redis'

runtimeOnly 'org.postgresql:postgresql'
implementation project(path: ':dateroad-common')
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package org.dateroad.Image.service;

import java.io.IOException;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.atomic.AtomicInteger;
import lombok.RequiredArgsConstructor;
import org.dateroad.code.FailureCode;
import org.dateroad.date.domain.Course;
import org.dateroad.exception.DateRoadException;
import org.dateroad.image.domain.Image;
import org.dateroad.image.repository.ImageRepository;
import org.dateroad.s3.S3Service;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

@Service
@RequiredArgsConstructor
@Transactional(readOnly = true)
public class ImageService {
private final ImageRepository imageRepository;
private final S3Service s3Service;
@Value("${aws-property.s3-bucket-name}")
private String path;
@Value("${cloudfront.domain}")
private String cachePath;

public List<Image> saveImages(final List<MultipartFile> images, final Course course) {
AtomicInteger sequence = new AtomicInteger();
List<Image> courseimages = images.stream()
.map(img -> {
try {
return Image.create(
course,
cachePath + s3Service.uploadImage(path, img).get(),
sequence.getAndIncrement()
);
} catch (IOException | ExecutionException | InterruptedException e) {
throw new RuntimeException(e);
}
})
.toList();
return imageRepository.saveAll(courseimages);
}

public Image findFirstByCourseOrderBySequenceAsc(Course course) {
return imageRepository.findFirstByCourseOrderBySequenceAsc(course)
.orElseThrow(
() -> new DateRoadException(FailureCode.COURSE_THUMBNAIL_NOT_FOUND)
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,13 @@

import lombok.RequiredArgsConstructor;
import org.dateroad.advertisment.dto.response.AdvGetAllRes;
import org.dateroad.advertisment.dto.response.AdvGetDetailRes;
import org.dateroad.advertisment.service.AdvertismentService;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

Expand All @@ -17,8 +20,13 @@ public class AdvertismentController {

@GetMapping
public ResponseEntity<AdvGetAllRes> getAllAdvertisments(){
return ResponseEntity
.status(HttpStatus.OK)
.body(advertismentService.getAllAdvertisments());
return ResponseEntity.ok(advertismentService.getAllAdvertisments());
}

@GetMapping("{advId}")
public ResponseEntity<AdvGetDetailRes> getAllAdvertisments(
final @PathVariable Long advId
){
return ResponseEntity.ok(advertismentService.getAdvertismentsDetail(advId));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package org.dateroad.advertisment.dto.response;

import com.fasterxml.jackson.annotation.JsonFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.List;
import lombok.AccessLevel;
import lombok.Builder;

@Builder(access = AccessLevel.PROTECTED)
public record AdvGetDetailRes(
List<AdvImagesRes> images,
String title,
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy.MM.dd", timezone = "Asia/Seoul")
LocalDate createAt,
String description
) {
public static AdvGetDetailRes of(List<AdvImagesRes> images, String title, LocalDate createAt, String description) {
return AdvGetDetailRes.builder()
.images(images)
.title(title)
.createAt(createAt)
.description(description)
.build();
}

@Builder(access = AccessLevel.PROTECTED)
public record AdvImagesRes(
String imagesUrl,
int sequence
) {
public static AdvImagesRes of(String imagesUrl, int sequence) {
return AdvImagesRes.builder()
.imagesUrl(imagesUrl)
.sequence(sequence)
.build();
}
}
}
Original file line number Diff line number Diff line change
@@ -1,23 +1,57 @@
package org.dateroad.advertisment.service;

import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import lombok.RequiredArgsConstructor;
import org.dateroad.adImage.domain.AdImage;
import org.dateroad.adImage.repository.AdImageRepository;
import org.dateroad.advertisement.domain.Advertisment;
import org.dateroad.advertisement.repository.AdvertismentRepository;
import org.dateroad.advertisment.dto.response.AdvGetAllRes;
import org.dateroad.advertisment.dto.response.AdvGetAllRes.AdvertismentDtoRes;
import org.dateroad.advertisment.dto.response.AdvGetDetailRes;
import org.dateroad.advertisment.dto.response.AdvGetDetailRes.AdvImagesRes;
import org.dateroad.code.FailureCode;
import org.dateroad.exception.EntityNotFoundException;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
@RequiredArgsConstructor
@Transactional(readOnly = true)
public class AdvertismentService {
private final AdvertismentRepository advertismentRepository;
private final AdImageRepository adImageRepository;

private static List<AdvImagesRes> getImages(final List<AdImage> adImages) {
return adImages.stream().map(
adImage -> AdvImagesRes.of(adImage.getImageUrl(), adImage.getSequence())
).toList();
}

public AdvGetAllRes getAllAdvertisments() {
Pageable topFive = PageRequest.of(0, 5);
return AdvGetAllRes.of(advertismentRepository.findTop5ByOrderByCreatedDateDesc(topFive).
stream()
.map(AdvertismentDtoRes::of)
.collect(Collectors.toList()));
}

public AdvGetDetailRes getAdvertismentsDetail(final Long advId) {
Advertisment advertisment = getAdvertisment(advId);
List<AdImage> adImages = adImageRepository.findAllById(advId);
return AdvGetDetailRes.of(
getImages(adImages), advertisment.getTitle(), advertisment.getCreatedAt().toLocalDate(),
advertisment.getTitle()
);
}

private Advertisment getAdvertisment(final Long advId) {
return advertismentRepository.findById(advId).orElseThrow(
() -> new EntityNotFoundException(FailureCode.ADVERTISMENT_NOT_FOUND)
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,13 @@ public class JwtGenerator {

public String generateAccessToken(final long userId) {
final Date now = new Date();
final Date expiryDate = generateExpirationDate(now);
final Date expireDate = generateExpirationDate(now);

return Jwts.builder()
.setHeaderParam(Header.TYPE, Header.JWT_TYPE)
.setSubject(String.valueOf(userId))
.setIssuedAt(now)
.setExpiration(expiryDate)
.setExpiration(expireDate)
.signWith(getSigningKey(), SignatureAlgorithm.HS256)
.compact();
}
Expand Down
19 changes: 19 additions & 0 deletions dateroad-api/src/main/java/org/dateroad/auth/jwt/JwtProvider.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,15 @@
import lombok.RequiredArgsConstructor;
import org.dateroad.auth.jwt.refreshtoken.RefreshTokenGenerator;
import org.dateroad.code.FailureCode;
import org.dateroad.exception.UnauthorizedException;
import org.dateroad.refreshtoken.domain.RefreshToken;
import org.dateroad.refreshtoken.repository.RefreshTokenRepository;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.Base64;

@RequiredArgsConstructor
@Component
public class JwtProvider {
Expand All @@ -20,6 +27,18 @@ public Token issueToken(final long userId) {
);
}

//refreshToken 재발급할 때 검증
public void validateRefreshToken(LocalDateTime expireDate) {
if (expireDate.isBefore(LocalDateTime.now())) {
throw new UnauthorizedException(FailureCode.EXPIRED_REFRESH_TOKEN);
}
}

//Base64 인코딩된 리프레시 토큰 문자열을 바이트 배열
private byte[] toBinary(String refreshToken) {
return Base64.getDecoder().decode(refreshToken);
}

public long getUserIdFromSubject(String token) {
Jws<Claims> jws = jwtGenerator.parseToken(token);
String subject = jws.getBody().getSubject();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@

import org.dateroad.code.FailureCode;
import org.dateroad.exception.UnauthorizedException;
import org.springframework.stereotype.Component;

public class JwtValidator {

public void equalRefreshToken(String refreshToken, String storedRefreshToken) {
if (!refreshToken.equals(storedRefreshToken)) {
throw new UnauthorizedException(FailureCode.UNAUTHORIZED);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.Base64;
import java.util.Optional;

@RequiredArgsConstructor
@Component
Expand All @@ -22,30 +23,19 @@ public class RefreshTokenGenerator {
public String generateRefreshToken(final long userId) {
SecureRandom random = createSecureRandom();

//SecureRandom을 사용하여 45 바이트의 랜덤 토큰을 생성
byte[] token = new byte[TOKEN_BYTE_SIZE];
random.nextBytes(token);
LocalDateTime expireAt = LocalDateTime.now().plusWeeks(2);
// SecureRandom을 사용하여 45 바이트의 랜덤 토큰을 생성
byte[] tokenBytes = new byte[TOKEN_BYTE_SIZE];
random.nextBytes(tokenBytes);

RefreshToken newRefreshToken = RefreshToken.create(token, userId, expireAt);
refreshTokenRepository.save(newRefreshToken);

return Base64.getEncoder().encodeToString(token);
}
// 바이트 배열을 Base64 인코딩하여 문자열로 변환
String token = Base64.getEncoder().encodeToString(tokenBytes);

//refreshToken 재발급할 때 검증
public Long getUserIdOrThrow(final String refreshToken) {
byte[] convertedRefreshToken = toBinary(refreshToken);
LocalDateTime expireAt = LocalDateTime.now().plusWeeks(4);

RefreshToken findRefreshToken = refreshTokenRepository.findUserIdByToken(Arrays.toString(convertedRefreshToken).getBytes());
if (findRefreshToken == null) {
throw new UnauthorizedException(FailureCode.INVALID_REFRESH_TOKEN_VALUE);
}
RefreshToken newRefreshToken = RefreshToken.create(token, userId, expireAt);
refreshTokenRepository.save(newRefreshToken);

if (findRefreshToken.getExpiredAt().isBefore(LocalDateTime.now())) {
throw new UnauthorizedException(FailureCode.EXPIRED_REFRESH_TOKEN);
}
return findRefreshToken.getUserId();
return token;
}

public void deleteRefreshToken(final Long userId) {
Expand All @@ -60,8 +50,4 @@ private SecureRandom createSecureRandom() {
return new SecureRandom(buffer.array());
}

//Base64 인코딩된 리프레시 토큰 문자열을 바이트 배열
private byte[] toBinary(String refreshToken) {
return Base64.getDecoder().decode(refreshToken);
}
}
12 changes: 12 additions & 0 deletions dateroad-api/src/main/java/org/dateroad/config/AsyncConfig.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package org.dateroad.config;

import java.util.concurrent.Executor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

@Configuration
@EnableAsync
public class AsyncConfig {
}
Loading

0 comments on commit 9e2bc41

Please sign in to comment.