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

Implement change-voucher owner to giftcard API #132

Merged
merged 5 commits into from
Oct 20, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@
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.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.swmaestro.repl.gifthub.giftcard.dto.GiftcardResponseDto;
import org.swmaestro.repl.gifthub.giftcard.service.GiftcardService;
import org.swmaestro.repl.gifthub.util.BasicAuthenticationDecoder;
import org.swmaestro.repl.gifthub.util.JwtProvider;
import org.swmaestro.repl.gifthub.util.Message;
import org.swmaestro.repl.gifthub.util.SuccessMessage;

Expand All @@ -24,6 +26,7 @@
@Tag(name = "GiftCard", description = "공유하기 관련 API")
public class GiftcardController {
private final GiftcardService giftcardService;
private final JwtProvider jwtProvider;

@GetMapping("/{id}")
@Operation(summary = "공유 정보 요청 메서드", description = "클라이언트에서 요청한 공유 정보를 전달하기 위한 메서드입니다.")
Expand All @@ -41,4 +44,21 @@ public ResponseEntity<Message> read(HttpServletRequest request, @PathVariable St
.data(giftcardResponseDto)
.build());
}

@PostMapping("/{id}/acquire")
@Operation(summary = "기프티콘 소유자 변경 메서드", description = "클라이언트의 요청을 통해 기프티콘 소유자를 변경하기 위한 메서드입니다.")
@ApiResponses({
@ApiResponse(responseCode = "200", description = "공유하기 정보 조회 성공"),
@ApiResponse(responseCode = "404", description = "존재하지 않는 공유하기 정보 접근")
})
public ResponseEntity<Message> changeVoucherUser(
HttpServletRequest request,
@PathVariable String id) {
String username = jwtProvider.getUsername(jwtProvider.resolveToken(request).substring(7));
giftcardService.changeVoucherUser(id, username);
return ResponseEntity.ok(
SuccessMessage.builder()
.path(request.getRequestURI())
.build());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -52,4 +52,8 @@ public Giftcard(String id, Voucher voucher, String message, LocalDateTime expire
this.password = password;
this.expiresAt = expiresAt;
}

public void expire() {
this.expiresAt = LocalDateTime.now();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@

import org.springframework.security.crypto.encrypt.AesBytesEncryptor;
import org.springframework.stereotype.Service;
import org.swmaestro.repl.gifthub.auth.entity.User;
import org.swmaestro.repl.gifthub.auth.service.UserService;
import org.swmaestro.repl.gifthub.exception.BusinessException;
import org.swmaestro.repl.gifthub.giftcard.config.GiftcardConfig;
import org.swmaestro.repl.gifthub.giftcard.dto.GiftcardResponseDto;
Expand All @@ -16,6 +18,7 @@
import org.swmaestro.repl.gifthub.util.StatusEnum;
import org.swmaestro.repl.gifthub.vouchers.dto.VoucherShareResponseDto;
import org.swmaestro.repl.gifthub.vouchers.entity.Voucher;
import org.swmaestro.repl.gifthub.vouchers.repository.VoucherRepository;

import lombok.RequiredArgsConstructor;

Expand All @@ -25,7 +28,15 @@ public class GiftcardService {
private final GiftcardRepository giftCardRepository;
private final GiftcardConfig giftcardConfig;
private final AesBytesEncryptor aesBytesEncryptor;

private final UserService userService;
private final VoucherRepository voucherRepository; // 순환 참조로 인해 vocuherService를 사용할 수 없음

/**
* 기프트 카드를 생성합니다.
* @param voucher: 기프트 카드를 생성할 기프티콘
* @param message: 기프트 카드에 담을 메시지
* @return: 생성된 기프트 카드의 id
*/
public VoucherShareResponseDto create(Voucher voucher, String message) {
if (isExist(voucher.getId())) {
throw new BusinessException("이미 공유된 기프티콘입니다.", StatusEnum.BAD_REQUEST);
Expand All @@ -45,14 +56,25 @@ public VoucherShareResponseDto create(Voucher voucher, String message) {
.build();
}

/**
* 기프트 카드를 조회합니다.
* @param id: 조회할 기프트 카드의 id
* @return: 조회된 기프트 카드
*/
public Giftcard read(String id) {
if (!isExist(id)) {
throw new BusinessException("존재하지 않는 링크입니다.", StatusEnum.NOT_FOUND);
throw new BusinessException("존재하지 않는 기프트 카드입니다.", StatusEnum.NOT_FOUND);
}

return giftCardRepository.findById(id).get();
}

/**
* 기프트 카드를 조회합니다.
* @param id: 조회할 기프트 카드의 id
* @param password: 조회할 기프트 카드의 비밀번호
* @return: 조회된 기프트 카드
*/
public GiftcardResponseDto read(String id, String password) {
Giftcard giftcard = read(id);

Expand All @@ -73,29 +95,80 @@ public GiftcardResponseDto read(String id, String password) {
.build();
}

/**
* 기프트 카드의 소유자를 변경합니다.
* @param giftcardId: 변경할 기프트 카드의 id
* @param username: 변경할 소유자의 username
* @return: 변경된 기프트 카드
*/
public Giftcard changeVoucherUser(String giftcardId, String username) {
Giftcard giftcard = read(giftcardId);

if (giftcard.getExpiresAt().isBefore(LocalDateTime.now())) {
throw new BusinessException("만료된 링크입니다.", StatusEnum.BAD_REQUEST);
}

Voucher updatedVoucher = giftcard.getVoucher();
User newUser = userService.read(username);
updatedVoucher.setUser(newUser);
voucherRepository.save(updatedVoucher);

giftcard.expire();
giftCardRepository.save(giftcard);
return giftcard;
}

/**
* 기프트 카드가 존재하는지 확인합니다. (기프트 카드 id로 확인)
* @param id
* @return
*/
public boolean isExist(String id) {
return giftCardRepository.existsById(id);
}

/**
* 기프트 카드가 존재하는지 확인합니다. (기프트 카드의 voucher id로 확인)
* @param voucherId: 기프트 카드의 id
* @return: 기프트 카드가 존재하는지 여부
*/
public boolean isExist(Long voucherId) {
return giftCardRepository.existsByVoucherId(voucherId);
}

/**
* UUID를 생성하는 메서드
* @return: 생성된 UUID
*/
public String generateUUID() {
return UUID.randomUUID().toString();
}

/**
* 4자리의 숫자로 구성된 비밀번호를 생성
* @return: 생성된 비밀번호
*/
public String generatePassword() {
int random = new Random().nextInt(10000);
return String.format("%04d", random);
}

/**
* 비밀번호 복호화 메서드
* @param password: 복호화할 비밀번호
* @return: 복호화된 비밀번호
*/
private String decryptPassword(String password) {
byte[] bytes = ByteArrayUtils.stringToByteArray(password);
byte[] decrypt = aesBytesEncryptor.decrypt(bytes);
return new String(decrypt, StandardCharsets.UTF_8);
}

/**
* 비밀번호 암호화 메서드
* @param password: 암호화할 비밀번호
* @return: 암호화된 비밀번호
*/
private String encryptPassword(String password) {
byte[] bytes = password.getBytes(StandardCharsets.UTF_8);
byte[] encrypt = aesBytesEncryptor.encrypt(bytes);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,10 @@
import org.springframework.security.test.context.support.WithMockUser;
import org.springframework.test.web.servlet.MockMvc;
import org.swmaestro.repl.gifthub.giftcard.dto.GiftcardResponseDto;
import org.swmaestro.repl.gifthub.giftcard.entity.Giftcard;
import org.swmaestro.repl.gifthub.giftcard.service.GiftcardService;
import org.swmaestro.repl.gifthub.util.JwtProvider;
import org.swmaestro.repl.gifthub.vouchers.entity.Voucher;

import com.fasterxml.jackson.databind.ObjectMapper;

Expand All @@ -31,6 +34,9 @@ class GiftcardControllerTest {
@MockBean
private GiftcardService giftcardService;

@MockBean
private JwtProvider jwtProvider;

@Test
@WithMockUser(username = "test", roles = "USER")
void read() throws Exception {
Expand Down Expand Up @@ -64,4 +70,35 @@ void read() throws Exception {
.andExpect(jsonPath("$.data.brand_name").value(giftcardResponseDto.getBrandName()))
.andExpect(jsonPath("$.data.expires_at").value(giftcardResponseDto.getExpiresAt().toString()));
}

@Test
@WithMockUser(username = "test", roles = "USER")
void changeVoucherUser() throws Exception {
// given
String giftcardId = "id";
String apiPath = "/giftcards/" + giftcardId + "/acquire";

Voucher voucher = Voucher.builder()
.id(1L)
.build();

Giftcard giftcard = Giftcard.builder()
.id(giftcardId)
.voucher(voucher)
.password("0000")
.message("메시지")
.expiresAt(LocalDate.now().atStartOfDay())
.build();

// when
when(jwtProvider.resolveToken(any())).thenReturn("my_awesome_access_token");
when(jwtProvider.getUsername(anyString())).thenReturn("test");
when(giftcardService.changeVoucherUser(giftcardId, "test")).thenReturn(giftcard);

// then
mockMvc.perform(post(apiPath)
.contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andExpect(jsonPath("$.path").value(apiPath));
}
}