diff --git a/src/main/java/inha/gdgoc/domain/manito/service/ManitoAdminService.java b/src/main/java/inha/gdgoc/domain/manito/service/ManitoAdminService.java index 8986f67..475320a 100644 --- a/src/main/java/inha/gdgoc/domain/manito/service/ManitoAdminService.java +++ b/src/main/java/inha/gdgoc/domain/manito/service/ManitoAdminService.java @@ -32,6 +32,7 @@ public class ManitoAdminService { private final ManitoSessionRepository sessionRepository; private final ManitoAssignmentRepository assignmentRepository; private final PasswordEncoder passwordEncoder; + private final ManitoPinPolicy manitoPinPolicy; // ✅ PIN 정책 주입 /** * 간단 CSV escape (콤마/따옴표/줄바꿈 포함 시 따옴표 감싸기) @@ -136,15 +137,9 @@ public void importParticipantsCsv(String sessionCode, MultipartFile file) { String studentId = cleanCsvField(cols[studentIdx]); String name = cleanCsvField(cols[nameIdx]); - String pinPlain = cleanCsvField(cols[pinIdx]); - pinPlain = pinPlain.replaceAll("\\D", ""); // 숫자만 추출 + String pinRaw = cleanCsvField(cols[pinIdx]); - if (pinPlain.length() > 4) { - pinPlain = pinPlain.substring(0, 4); // 혹시 4자리 넘으면 앞 4자리 - } - - // zero padding to 4 digits - pinPlain = String.format("%04d", Integer.parseInt(pinPlain)); + String pinPlain = manitoPinPolicy.normalize(pinRaw); name = name.replace("`", "").trim(); @@ -153,13 +148,6 @@ public void importParticipantsCsv(String sessionCode, MultipartFile file) { continue; } - // 여기서 PIN 길이 정책은 네가 선택 - // - 그대로 쓰기 - // - 숫자만 남기고 4자리 zero padding 하기 등 - // ex) 숫자만 추출: - // pinPlain = pinPlain.replaceAll("\\D", ""); - // if (pinPlain.length() < 4) { ... } - String pinHash = passwordEncoder.encode(pinPlain); var existingOpt = assignmentRepository.findBySessionAndStudentId(session, studentId); diff --git a/src/main/java/inha/gdgoc/domain/manito/service/ManitoPinPolicy.java b/src/main/java/inha/gdgoc/domain/manito/service/ManitoPinPolicy.java new file mode 100644 index 0000000..1374c62 --- /dev/null +++ b/src/main/java/inha/gdgoc/domain/manito/service/ManitoPinPolicy.java @@ -0,0 +1,29 @@ +package inha.gdgoc.domain.manito.service; + +import inha.gdgoc.global.exception.BusinessException; +import inha.gdgoc.global.exception.GlobalErrorCode; +import org.springframework.stereotype.Component; + +@Component +public class ManitoPinPolicy { + public String normalize(String rawPin) { + if (rawPin == null) { + throw new BusinessException(GlobalErrorCode.BAD_REQUEST, "PIN 값이 비어 있습니다."); + } + + // 숫자만 추출 + String digits = rawPin.replaceAll("\\D", ""); + + if (digits.isEmpty()) { + throw new BusinessException(GlobalErrorCode.BAD_REQUEST, "PIN 값에는 적어도 1자리 이상의 숫자가 있어야 합니다."); + } + + // 4자리 zero-padding + try { + int asInt = Integer.parseInt(digits); + return String.format("%04d", asInt); + } catch (NumberFormatException e) { + throw new BusinessException(GlobalErrorCode.BAD_REQUEST, "PIN 형식이 올바르지 않습니다."); + } + } +} \ No newline at end of file diff --git a/src/main/java/inha/gdgoc/domain/manito/service/ManitoUserService.java b/src/main/java/inha/gdgoc/domain/manito/service/ManitoUserService.java index 9f9f46e..af29150 100644 --- a/src/main/java/inha/gdgoc/domain/manito/service/ManitoUserService.java +++ b/src/main/java/inha/gdgoc/domain/manito/service/ManitoUserService.java @@ -17,6 +17,7 @@ public class ManitoUserService { private final ManitoSessionRepository sessionRepository; private final ManitoAssignmentRepository assignmentRepository; private final PasswordEncoder passwordEncoder; + private final ManitoPinPolicy manitoPinPolicy; // ✅ PIN 정책 주입 /** * pin 검증 후 암호문 반환 @@ -29,7 +30,14 @@ public String verifyAndGetCipher(String sessionCode, String studentId, String pi ManitoAssignment assignment = assignmentRepository.findBySessionAndStudentId(session, studentId) .orElseThrow(() -> new BusinessException(GlobalErrorCode.RESOURCE_NOT_FOUND, "해당 학번은 세션에 참여하지 않았습니다.")); - if (!passwordEncoder.matches(pinPlain, assignment.getPinHash())) { + // ✅ Admin 쪽과 동일한 규칙으로 PIN 정규화 + String normalizedPin = manitoPinPolicy.normalize(pinPlain); + + if (normalizedPin.isEmpty()) { + throw new BusinessException(GlobalErrorCode.BAD_REQUEST, "PIN 형식이 올바르지 않습니다."); + } + + if (!passwordEncoder.matches(normalizedPin, assignment.getPinHash())) { throw new BusinessException(GlobalErrorCode.FORBIDDEN_USER, "PIN이 일치하지 않습니다."); }