Skip to content
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 @@ -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 (콤마/따옴표/줄바꿈 포함 시 따옴표 감싸기)
Expand Down Expand Up @@ -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();

Expand All @@ -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);
Expand Down
Original file line number Diff line number Diff line change
@@ -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 형식이 올바르지 않습니다.");
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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 검증 후 암호문 반환
Expand All @@ -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이 일치하지 않습니다.");
}

Expand Down
Loading