Skip to content

Commit

Permalink
Merge pull request #41 from softeerbootcamp4th/feat/sharelink
Browse files Browse the repository at this point in the history
[Feature] 유형검사 결과 확인/제출 로직 분리 및 공유 링크 생성 api 추가
  • Loading branch information
eckrin authored Aug 8, 2024
2 parents ee3cd10 + aee86c0 commit 3e0fbda
Show file tree
Hide file tree
Showing 33 changed files with 625 additions and 106 deletions.
4 changes: 3 additions & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,9 @@ repositories {
}

dependencies {
//redis
// thymeleaf
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
// redis
implementation 'org.springframework.boot:spring-boot-starter-data-redis'
// sms
implementation 'net.nurigo:sdk:4.2.7'
Expand Down
2 changes: 1 addition & 1 deletion script/start.sh
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ cp $PROJECT_ROOT/build/libs/*.jar $JAR_FILE

# jar 파일 실행
echo "$TIME_NOW > $JAR_FILE 파일 실행" >> $DEPLOY_LOG
nohup java -jar $JAR_FILE > $APP_LOG 2> $ERROR_LOG &
nohup java -jar -Duser.timezone=Asia/Seoul $JAR_FILE > $APP_LOG 2> $ERROR_LOG &

CURRENT_PID=$(pgrep -f $JAR_FILE)
echo "$TIME_NOW > 실행된 프로세스 아이디 $CURRENT_PID 입니다." >> $DEPLOY_LOG
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.softeer.podo.common.entity.DateEntity;
import com.softeer.podo.event.model.entity.LotsComment;
import com.softeer.podo.event.model.entity.TestResult;
import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Builder;
Expand All @@ -21,6 +22,11 @@ public class LotsUser extends DateEntity {
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "user_id")
private Long id;

@ManyToOne
@JoinColumn(name = "result_id")
private TestResult testResult;

private String name;
@Column(name = "phone_number", unique = true)
private String phoneNum;
Expand All @@ -29,4 +35,5 @@ public class LotsUser extends DateEntity {
private Role role;
@OneToOne(mappedBy = "lotsUser", orphanRemoval = true, cascade = CascadeType.ALL)
private LotsComment lotsComment;

}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
import com.softeer.podo.admin.model.entity.LotsUser;
import org.springframework.data.jpa.repository.JpaRepository;

import java.util.Optional;

public interface LotsUserRepository extends JpaRepository<LotsUser, Long> {
LotsUser findByNameAndPhoneNum(String name, String phoneNum);
Optional<LotsUser> findByPhoneNum(String phoneNum);
boolean existsByPhoneNum(String phoneNum);
}
5 changes: 5 additions & 0 deletions src/main/java/com/softeer/podo/common/response/ErrorCode.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@ public enum ErrorCode {
INVALID_SELECTION_ERROR(false, HttpStatus.BAD_REQUEST.value(), "선택지 형식이 잘못되었습니다."),
USER_NOT_EXIST_ERROR(false, HttpStatus.BAD_REQUEST.value(), "해당 사용자가 아직 이벤트에 응모하지 않았습니다."),
EXISTING_COMMENT_ERROR(false, HttpStatus.BAD_REQUEST.value(),"이미 기대평을 작성했습니다."),
LOTS_LINK_NOT_EXISTS_ERROR(false, HttpStatus.INTERNAL_SERVER_ERROR.value(),"공유 링크가 정상적으로 생성되지 않았습니다."),
INVALID_RESULT_TYPE_ERROR(false, HttpStatus.INTERNAL_SERVER_ERROR.value(),"존재하지 않는 드라이버 유형입니다."),

//etc
AES_ENC_DEC_ERROR(false, HttpStatus.INTERNAL_SERVER_ERROR.value(),"공유링크 생성중 오류가 발생했습니다."),

//admin
EVENT_NOT_FOUND_ERROR(false, HttpStatus.INTERNAL_SERVER_ERROR.value(),"해당 이벤트를 찾을 수 없습니다."),
Expand Down
48 changes: 48 additions & 0 deletions src/main/java/com/softeer/podo/common/utils/AESUtils.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package com.softeer.podo.common.utils;

import jakarta.annotation.PostConstruct;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Base64;

@Component
public class AESUtils {
private static final String ALGORITHM = "AES";

@Value("${secret.jwt}")
private String baseSecretKey;

private static String STATIC_BASE_SECRET_KEY;

@PostConstruct
public void init() {
STATIC_BASE_SECRET_KEY = this.baseSecretKey;
}

public static String encrypt(String data) throws Exception {
Cipher cipher = Cipher.getInstance(ALGORITHM);
cipher.init(Cipher.ENCRYPT_MODE, makeSecretKeyByString(STATIC_BASE_SECRET_KEY));
byte[] encryptedData = cipher.doFinal(data.getBytes());
return Base64.getEncoder().encodeToString(encryptedData);
}

public static String decrypt(String encryptedData) throws Exception {
Cipher cipher = Cipher.getInstance(ALGORITHM);
cipher.init(Cipher.DECRYPT_MODE, makeSecretKeyByString(STATIC_BASE_SECRET_KEY));
byte[] decryptedData = cipher.doFinal(Base64.getDecoder().decode(encryptedData));
return new String(decryptedData);
}

// 특정 문자열을 기반으로 SecretKey 객체를 생성하는 메서드
public static SecretKey makeSecretKeyByString(String password) {
byte[] keyBytes = password.getBytes(StandardCharsets.UTF_8);
keyBytes = Arrays.copyOf(keyBytes, 16); // 128비트(16바이트)로 맞추기
return new SecretKeySpec(keyBytes, ALGORITHM);
}
}
42 changes: 42 additions & 0 deletions src/main/java/com/softeer/podo/common/utils/URLUtils.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package com.softeer.podo.common.utils;

import org.springframework.stereotype.Component;

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;

@Component
public class URLUtils {

/**
* 주어진 문자열을 URL 인코딩합니다.
*
* @param value 인코딩할 문자열
* @return URL 인코딩된 문자열
*/
public static String encode(String value) throws UnsupportedEncodingException {
return URLEncoder.encode(value, StandardCharsets.UTF_8);
}

/**
* 주어진 URL 인코딩된 문자열을 디코딩합니다.
*
* @param value 디코딩할 문자열
* @return URL 디코딩된 문자열
* @throws UnsupportedEncodingException 디코딩이 지원되지 않는 경우 발생
*/
public static String decode(String value) throws UnsupportedEncodingException {
return URLDecoder.decode(value, StandardCharsets.UTF_8);
}

public static void main(String[] args) {
try {
String uniqueLink = "V1a1Vrqe1oBYCkqkXs7/Uw==";
String encodedLink = encode(uniqueLink);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package com.softeer.podo.event.controller;

import com.softeer.podo.common.response.CommonResponse;
import com.softeer.podo.event.model.dto.LotsTypeRequestDto;
import com.softeer.podo.event.model.dto.LotsTypeResponseDto;
import com.softeer.podo.event.service.EventLotsService;
import io.swagger.v3.oas.annotations.Operation;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RequestMapping("/lots")
@RestController
@RequiredArgsConstructor
public class EventLotsApiController {

private final EventLotsService eventLotsService;

/**
* 제출한 유형테스트 결과에 따라 적절한 드라이버 유형 반환
*/
@PostMapping("/type")
@Operation(summary = "제출한 유형테스트 결과에 따라 적절한 드라이버 유형 반환")
public CommonResponse<LotsTypeResponseDto> getDriverType(@Valid @RequestBody LotsTypeRequestDto dto) {
return new CommonResponse<>(eventLotsService.getProperDriverType(dto));
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package com.softeer.podo.event.controller;


import com.softeer.podo.common.response.CommonResponse;
import com.softeer.podo.event.model.dto.LotsApplicationRequestDto;
import com.softeer.podo.event.model.dto.LotsApplicationResponseDto;
Expand All @@ -12,28 +11,34 @@
import io.swagger.v3.oas.annotations.Operation;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/v1/lots")
@RestController
@RequiredArgsConstructor
@Slf4j
public class EventLotsController {

private final EventLotsService eventLotsService;

@PostMapping("/application")
@Operation(summary = "유형테스트 결과 제출 Api")
public CommonResponse<LotsApplicationResponseDto> eventApplication(@Auth AuthInfo authInfo,
@Valid @RequestBody LotsApplicationRequestDto dto) {
return new CommonResponse<>(eventLotsService.applyLotsEvent(authInfo, dto));
}

@PostMapping("/comment")
@Operation(summary = "랜덤추천이벤트 기대평 등록용 Api")
public CommonResponse<LotsCommentResponseDto> eventComment(@Auth AuthInfo authInfo,
@Valid @RequestBody LotsCommentRequestDto dto) {
return new CommonResponse<>(eventLotsService.comment(authInfo, dto));
public CommonResponse<LotsCommentResponseDto> eventComment(
@Auth AuthInfo authInfo,
@Valid @RequestBody LotsCommentRequestDto dto
) {
return new CommonResponse<>(eventLotsService.registerComment(authInfo, dto));
}

@PostMapping("/application")
@Operation(summary = "랜덤추첨 이벤트 응모하기")
public CommonResponse<LotsApplicationResponseDto> applyEvent(
@Auth AuthInfo authInfo,
@Valid @RequestBody LotsApplicationRequestDto dto
) {
return new CommonResponse<>(eventLotsService.applyEvent(authInfo, dto));
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package com.softeer.podo.event.controller;

import com.softeer.podo.event.service.EventLotsService;
import io.swagger.v3.oas.annotations.Operation;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;

@RequestMapping("/lots")
@Controller
@RequiredArgsConstructor
public class EventLotsPageController {

private final EventLotsService eventLotsService;

/**
* 고유 공유링크 클릭
* {uniqueLink}: 유저 id (암호화)
*/
@GetMapping("/link/{uniqueLink}")
@Operation(summary = "공유링크 클릭시 redirection하기 위함 (사용자 직접 호출용)")
public String shareLinkClick(
HttpServletResponse response,
@PathVariable String uniqueLink
) {
try {
// 해당 유저에 해당하는 적절한 이벤트 결과 페이지 찾기
String redirectUrl = eventLotsService.getEventUrl(uniqueLink);
// 이벤트 결과 페이지 반환
// response.setStatus(HttpServletResponse.SC_FOUND);
// response.setHeader("Location", "/type/"+redirectUrl);
return "/type/"+redirectUrl;
} catch (Exception e) {
// 에러 페이지로 리다이렉션
// response.setStatus(HttpServletResponse.SC_FOUND);
// response.setHeader("Location", "/error/404");
return "/error/404";
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.softeer.podo.event.exception;


import lombok.AllArgsConstructor;
import lombok.Getter;

@Getter
@AllArgsConstructor
public class AESExecutionException extends RuntimeException {
private String message;
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,28 +17,49 @@ public class EventExceptionHandler {
@ExceptionHandler(ExistingUserException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
public CommonResponse<?> existingPhoneNumbException(ExistingUserException e, HttpServletRequest request) {
log.warn("LOTSAPPLICATION-001> 요청 URI: " + request.getRequestURI() + ", 에러 메세지: " + e.getMessage());
log.warn("LOTS-001> 요청 URI: " + request.getRequestURI() + ", 에러 메세지: " + e.getMessage());
return new CommonResponse<>(ErrorCode.PHONENUM_EXIST_ERROR);
}

@ExceptionHandler(InvalidSelectionException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
public CommonResponse<?> invalidSelectionException(InvalidSelectionException e, HttpServletRequest request) {
log.warn("LOTSAPPLICATION-002> 요청 URI: " + request.getRequestURI() + ", 에러 메세지: " + e.getMessage());
log.warn("LOTS-002> 요청 URI: " + request.getRequestURI() + ", 에러 메세지: " + e.getMessage());
return new CommonResponse<>(ErrorCode.INVALID_SELECTION_ERROR);
}

@ExceptionHandler(UserNotExistException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
public CommonResponse<?> userNotExistException(UserNotExistException e, HttpServletRequest request) {
log.warn("LOTSAPPLICATION-003> 요청 URI: " + request.getRequestURI() + ", 에러 메세지: " + e.getMessage());
log.warn("LOTS-003> 요청 URI: " + request.getRequestURI() + ", 에러 메세지: " + e.getMessage());
return new CommonResponse<>(ErrorCode.USER_NOT_EXIST_ERROR);
}

@ExceptionHandler(ExistingCommentException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
public CommonResponse<?> existingCommentException(ExistingCommentException e, HttpServletRequest request) {
log.warn("LOTSAPPLICATION-004> 요청 URI: " + request.getRequestURI() + ", 에러 메세지: " + e.getMessage());
log.warn("LOTS-004> 요청 URI: " + request.getRequestURI() + ", 에러 메세지: " + e.getMessage());
return new CommonResponse<>(ErrorCode.EXISTING_COMMENT_ERROR);
}

@ExceptionHandler(LotsShareLinkNotExistsException.class)
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
public CommonResponse<?> lotsShareLinkNotExistsException(LotsShareLinkNotExistsException e, HttpServletRequest request) {
log.warn("LOTS-005> 요청 URI: " + request.getRequestURI() + ", 에러 메세지: " + e.getMessage());
return new CommonResponse<>(ErrorCode.LOTS_LINK_NOT_EXISTS_ERROR);
}

@ExceptionHandler(AESExecutionException.class)
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
public CommonResponse<?> AESExecutionException(AESExecutionException e, HttpServletRequest request) {
log.warn("LOTS-006> 요청 URI: " + request.getRequestURI() + ", 에러 메세지: " + e.getMessage());
return new CommonResponse<>(ErrorCode.AES_ENC_DEC_ERROR);
}

@ExceptionHandler(InvalidResultTypeException.class)
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
public CommonResponse<?> invalidResultTypeException(InvalidResultTypeException e, HttpServletRequest request) {
log.warn("LOTS-007> 요청 URI: " + request.getRequestURI() + ", 에러 메세지: " + e.getMessage());
return new CommonResponse<>(ErrorCode.INVALID_RESULT_TYPE_ERROR);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.softeer.podo.event.exception;


import lombok.AllArgsConstructor;
import lombok.Getter;

@Getter
@AllArgsConstructor
public class InvalidResultTypeException extends RuntimeException {
private String message;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.softeer.podo.event.exception;


import lombok.AllArgsConstructor;
import lombok.Getter;

@Getter
@AllArgsConstructor
public class LotsShareLinkNotExistsException extends RuntimeException {
private String message;
}
Loading

0 comments on commit 3e0fbda

Please sign in to comment.