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 @@ -13,6 +13,7 @@
import com.assu.server.domain.auth.dto.ssu.USaintAuthResponse;
import com.assu.server.domain.auth.service.*;
import com.assu.server.domain.user.entity.enums.University;
import com.assu.server.domain.auth.dto.verification.VerificationRequestDTO;
import com.assu.server.global.apiPayload.BaseResponse;
import com.assu.server.global.apiPayload.code.status.SuccessStatus;
import io.swagger.v3.oas.annotations.Operation;
Expand Down Expand Up @@ -41,6 +42,7 @@ public class AuthController {
private final LogoutService logoutService;
private final SSUAuthService ssuAuthService;
private final WithdrawalService withdrawalService;
private final VerificationService verificationService;

@Operation(
summary = "휴대폰 인증번호 발송 API",
Expand Down Expand Up @@ -82,6 +84,36 @@ public BaseResponse<Void> checkAuthNumber(
return BaseResponse.onSuccess(SuccessStatus.VERIFY_AUTH_NUMBER_SUCCESS, null);
}

@Operation(summary = "전화번호 중복 체크 API", description = "# [v1.0 (2025-01-15)]\n" +
"- 입력한 전화번호가 이미 가입된 사용자가 있는지 확인합니다.\n" +
"- 중복된 전화번호가 있으면 에러를 반환합니다.\n" +
"\n**Request Body:**\n" +
" - `phoneNumber` (String, required): 확인할 전화번호 (010XXXXXXXX 형식)\n" +
"\n**Response:**\n" +
" - 성공 시 200(OK)과 사용 가능 메시지 반환\n" +
" - 중복 시 404(NOT_FOUND)와 에러 메시지 반환")
@PostMapping("/phone-verification/check")
public BaseResponse<Void> checkPhoneNumberAvailability(
@RequestBody @Valid VerificationRequestDTO.PhoneVerificationCheckRequest request) {
verificationService.checkPhoneNumberAvailability(request);
return BaseResponse.onSuccess(SuccessStatus._OK, null);
}

@Operation(summary = "이메일 중복 체크 API", description = "# [v1.0 (2025-01-15)]\n" +
"- 입력한 이메일이 이미 가입된 사용자가 있는지 확인합니다.\n" +
"- 중복된 이메일이 있으면 에러를 반환합니다.\n" +
"\n**Request Body:**\n" +
" - `email` (String, required): 확인할 이메일 주소\n" +
"\n**Response:**\n" +
" - 성공 시 200(OK)과 사용 가능 메시지 반환\n" +
" - 중복 시 404(NOT_FOUND)와 에러 메시지 반환")
@PostMapping("/email-verification/check")
public BaseResponse<Void> checkEmailAvailability(
@RequestBody @Valid VerificationRequestDTO.EmailVerificationCheckRequest request) {
verificationService.checkEmailAvailability(request);
return BaseResponse.onSuccess(SuccessStatus._OK, null);
}

@Operation(
summary = "학생 회원가입 API",
description = "# [v1.2 (2025-09-13)](https://clumsy-seeder-416.notion.site/2241197c19ed81129c85cf5bbe1f7971)\n" +
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package com.assu.server.domain.auth.dto.verification;

import jakarta.validation.constraints.Email;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Pattern;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

public class VerificationRequestDTO {

@Builder
@Getter
@NoArgsConstructor
@AllArgsConstructor
public static class PhoneVerificationCheckRequest {
@NotBlank(message = "전화번호는 필수입니다.")
@Pattern(regexp = "^010\\d{8}$", message = "올바른 전화번호 형식이 아닙니다.")
private String phoneNumber;
}

@Builder
@Getter
@NoArgsConstructor
@AllArgsConstructor
public static class EmailVerificationCheckRequest {
@NotBlank(message = "이메일은 필수입니다.")
@Email(message = "올바른 이메일 형식이 아닙니다.")
private String email;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -136,20 +136,81 @@ public USaintAuthResponse uSaintAuth(USaintAuthRequest uSaintAuthRequest) {

// 매핑된 Enum 값 저장
switch (majorStr) {
// 인문대학
case "기독교학과" -> usaintAuthResponse.setMajor(Major.CHRISTIAN_STUDIES);
case "국어국문학과" -> usaintAuthResponse.setMajor(Major.KOREAN_LITERATURE);
case "영어영문학과" -> usaintAuthResponse.setMajor(Major.ENGLISH_LITERATURE);
case "독어독문학과" -> usaintAuthResponse.setMajor(Major.GERMAN_LITERATURE);
case "불어불문학과" -> usaintAuthResponse.setMajor(Major.FRENCH_LITERATURE);
case "중어중문학과" -> usaintAuthResponse.setMajor(Major.CHINESE_LITERATURE);
case "일어일문학과" -> usaintAuthResponse.setMajor(Major.JAPANESE_LITERATURE);
case "철학과" -> usaintAuthResponse.setMajor(Major.PHILOSOPHY);
case "사학과" -> usaintAuthResponse.setMajor(Major.HISTORY);
case "예술창작학부" -> usaintAuthResponse.setMajor(Major.CREATIVE_ARTS);
case "스포츠학부" -> usaintAuthResponse.setMajor(Major.SPORTS);

// 자연과학대학
case "수학과" -> usaintAuthResponse.setMajor(Major.MATHEMATICS);
case "화학과" -> usaintAuthResponse.setMajor(Major.CHEMISTRY);
case "의생명시스템학부" -> usaintAuthResponse.setMajor(Major.BIOMEDICAL_SYSTEMS);
case "물리학과" -> usaintAuthResponse.setMajor(Major.PHYSICS);
case "정보통계ㆍ보험수리학과" -> usaintAuthResponse.setMajor(Major.STATISTICS_ACTUARIAL);

// 법과대학
case "법학과" -> usaintAuthResponse.setMajor(Major.LAW);
case "국제법무학과" -> usaintAuthResponse.setMajor(Major.INTERNATIONAL_LAW);

// 사회과학대학
case "사회복지학부" -> usaintAuthResponse.setMajor(Major.SOCIAL_WELFARE);
case "정치외교학과" -> usaintAuthResponse.setMajor(Major.POLITICAL_SCIENCE);
case "언론홍보학과" -> usaintAuthResponse.setMajor(Major.MEDIA_COMMUNICATION);
case "행정학부" -> usaintAuthResponse.setMajor(Major.PUBLIC_ADMINISTRATION);
case "정보사회학과" -> usaintAuthResponse.setMajor(Major.INFORMATION_SOCIETY);
case "평생교육학과" -> usaintAuthResponse.setMajor(Major.LIFELONG_EDUCATION);

// 경제통상대학
case "경제학과" -> usaintAuthResponse.setMajor(Major.ECONOMICS);
case "금융경제학과" -> usaintAuthResponse.setMajor(Major.FINANCIAL_ECONOMICS);
case "글로벌통상학과" -> usaintAuthResponse.setMajor(Major.GLOBAL_TRADE);
case "국제무역학과" -> usaintAuthResponse.setMajor(Major.INTERNATIONAL_TRADE);

// 경영대학
case "경영학부" -> usaintAuthResponse.setMajor(Major.BUSINESS_ADMINISTRATION);
case "회계학과" -> usaintAuthResponse.setMajor(Major.ACCOUNTING);
case "벤처경영학과" -> usaintAuthResponse.setMajor(Major.VENTURE_MANAGEMENT);
case "복지경영학과" -> usaintAuthResponse.setMajor(Major.WELFARE_MANAGEMENT);
case "벤처중소기업학과" -> usaintAuthResponse.setMajor(Major.VENTURE_SME);
case "금융학부" -> usaintAuthResponse.setMajor(Major.FINANCE);
case "혁신경영학과" -> usaintAuthResponse.setMajor(Major.INNOVATION_MANAGEMENT);
case "회계세무학과" -> usaintAuthResponse.setMajor(Major.ACCOUNTING_TAX);

// 공과대학
case "화학공학과" -> usaintAuthResponse.setMajor(Major.CHEMICAL_ENGINEERING);
case "전기공학부" -> usaintAuthResponse.setMajor(Major.ELECTRICAL_ENGINEERING);
case "건축학부" -> usaintAuthResponse.setMajor(Major.ARCHITECTURE);
case "산업ㆍ정보시스템공학과" -> usaintAuthResponse.setMajor(Major.INDUSTRIAL_INFO_SYSTEMS);
case "기계공학부" -> usaintAuthResponse.setMajor(Major.MECHANICAL_ENGINEERING);
case "신소재공학과" -> usaintAuthResponse.setMajor(Major.MATERIALS_SCIENCE);

// IT대학
case "컴퓨터학부" -> usaintAuthResponse.setMajor(Major.COM);
case "소프트웨어학부" -> usaintAuthResponse.setMajor(Major.SW);
case "글로벌미디어학부" -> usaintAuthResponse.setMajor(Major.GM);
case "미디어경영학과" -> usaintAuthResponse.setMajor(Major.MB);
case "AI융합학부" -> usaintAuthResponse.setMajor(Major.AI);
case "전자정보공학부" -> usaintAuthResponse.setMajor(Major.EE);
case "정보보호학과" -> usaintAuthResponse.setMajor(Major.IP);

// 자유전공학부
case "자유전공학부" -> usaintAuthResponse.setMajor(Major.LIBERAL_ARTS);

default -> {
log.debug("{} is not a supported major.", majorStr);
throw new CustomAuthException(ErrorStatus.SSU_SAINT_UNSUPPORTED_MAJOR);
}
}
}
case "과정/학적" -> usaintAuthResponse.setEnrollmentStatus(strong.text());
case "과정/학기" -> usaintAuthResponse.setEnrollmentStatus(strong.text());
case "학년/학기" -> usaintAuthResponse.setYearSemester(strong.text());
}
}
Expand All @@ -164,8 +225,8 @@ private ResponseEntity<String> requestUSaintSSO(String sToken, String sIdno) {
.uri(url)
.header("Cookie", "sToken=" + sToken + "; sIdno=" + sIdno)
.retrieve()
.toEntity(String.class) // ResponseEntity<String> 전체 반환 (body + header 포함)
.block(); // 동기 방식
.toEntity(String.class) // ResponseEntity<String> 전체 반환 (body + header 포함)
.block(); // 동기 방식
}

private ResponseEntity<String> requestUSaintPortal(StringBuilder cookie) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.assu.server.domain.auth.service;

import com.assu.server.domain.auth.dto.verification.VerificationRequestDTO;

public interface VerificationService {
void checkPhoneNumberAvailability(
VerificationRequestDTO.PhoneVerificationCheckRequest request);

void checkEmailAvailability(
VerificationRequestDTO.EmailVerificationCheckRequest request);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package com.assu.server.domain.auth.service;

import com.assu.server.domain.auth.dto.verification.VerificationRequestDTO;
import com.assu.server.domain.auth.exception.CustomAuthException;
import com.assu.server.domain.auth.repository.CommonAuthRepository;
import com.assu.server.domain.member.repository.MemberRepository;
import com.assu.server.global.apiPayload.code.status.ErrorStatus;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

@Service
@RequiredArgsConstructor
public class VerificationServiceImpl implements VerificationService {

private final MemberRepository memberRepository;
private final CommonAuthRepository commonAuthRepository;

@Override
public void checkPhoneNumberAvailability(
VerificationRequestDTO.PhoneVerificationCheckRequest request) {

boolean exists = memberRepository.existsByPhoneNum(request.getPhoneNumber());

if (exists) {
throw new CustomAuthException(ErrorStatus.EXISTED_PHONE);
}
}

@Override
public void checkEmailAvailability(
VerificationRequestDTO.EmailVerificationCheckRequest request) {

boolean exists = commonAuthRepository.existsByEmail(request.getEmail());

if (exists) {
throw new CustomAuthException(ErrorStatus.EXISTED_EMAIL);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,15 @@
package com.assu.server.domain.user.entity.enums;

public enum Department {
IT("IT대학");
HUMANITIES("인문대학"),
NATURAL_SCIENCE("자연과학대학"),
LAW("법과대학"),
SOCIAL_SCIENCE("사회과학대학"),
ECONOMICS("경제통상대학"),
BUSINESS("경영대학"),
ENGINEERING("공과대학"),
IT("IT대학"),
LIBERAL_ARTS("자유전공학부");

private final String displayName;

Expand Down
66 changes: 63 additions & 3 deletions src/main/java/com/assu/server/domain/user/entity/enums/Major.java
Original file line number Diff line number Diff line change
@@ -1,13 +1,73 @@
package com.assu.server.domain.user.entity.enums;

public enum Major {
// 인문대학
CHRISTIAN_STUDIES(Department.HUMANITIES, "기독교학과"),
KOREAN_LITERATURE(Department.HUMANITIES, "국어국문학과"),
ENGLISH_LITERATURE(Department.HUMANITIES, "영어영문학과"),
GERMAN_LITERATURE(Department.HUMANITIES, "독어독문학과"),
FRENCH_LITERATURE(Department.HUMANITIES, "불어불문학과"),
CHINESE_LITERATURE(Department.HUMANITIES, "중어중문학과"),
JAPANESE_LITERATURE(Department.HUMANITIES, "일어일문학과"),
PHILOSOPHY(Department.HUMANITIES, "철학과"),
HISTORY(Department.HUMANITIES, "사학과"),
CREATIVE_ARTS(Department.HUMANITIES, "예술창작학부"),
SPORTS(Department.HUMANITIES, "스포츠학부"),

// 자연과학대학
MATHEMATICS(Department.NATURAL_SCIENCE, "수학과"),
CHEMISTRY(Department.NATURAL_SCIENCE, "화학과"),
BIOMEDICAL_SYSTEMS(Department.NATURAL_SCIENCE, "의생명시스템학부"),
PHYSICS(Department.NATURAL_SCIENCE, "물리학과"),
STATISTICS_ACTUARIAL(Department.NATURAL_SCIENCE, "정보통계ㆍ보험수리학과"),

// 법과대학
LAW(Department.LAW, "법학과"),
INTERNATIONAL_LAW(Department.LAW, "국제법무학과"),

// 사회과학대학
SOCIAL_WELFARE(Department.SOCIAL_SCIENCE, "사회복지학부"),
POLITICAL_SCIENCE(Department.SOCIAL_SCIENCE, "정치외교학과"),
MEDIA_COMMUNICATION(Department.SOCIAL_SCIENCE, "언론홍보학과"),
PUBLIC_ADMINISTRATION(Department.SOCIAL_SCIENCE, "행정학부"),
INFORMATION_SOCIETY(Department.SOCIAL_SCIENCE, "정보사회학과"),
LIFELONG_EDUCATION(Department.SOCIAL_SCIENCE, "평생교육학과"),

// 경제통상대학
ECONOMICS(Department.ECONOMICS, "경제학과"),
FINANCIAL_ECONOMICS(Department.ECONOMICS, "금융경제학과"),
GLOBAL_TRADE(Department.ECONOMICS, "글로벌통상학과"),
INTERNATIONAL_TRADE(Department.ECONOMICS, "국제무역학과"),

// 경영대학
BUSINESS_ADMINISTRATION(Department.BUSINESS, "경영학부"),
ACCOUNTING(Department.BUSINESS, "회계학과"),
VENTURE_MANAGEMENT(Department.BUSINESS, "벤처경영학과"),
WELFARE_MANAGEMENT(Department.BUSINESS, "복지경영학과"),
VENTURE_SME(Department.BUSINESS, "벤처중소기업학과"),
FINANCE(Department.BUSINESS, "금융학부"),
INNOVATION_MANAGEMENT(Department.BUSINESS, "혁신경영학과"),
ACCOUNTING_TAX(Department.BUSINESS, "회계세무학과"),

// 공과대학
CHEMICAL_ENGINEERING(Department.ENGINEERING, "화학공학과"),
ELECTRICAL_ENGINEERING(Department.ENGINEERING, "전기공학부"),
ARCHITECTURE(Department.ENGINEERING, "건축학부"),
INDUSTRIAL_INFO_SYSTEMS(Department.ENGINEERING, "산업ㆍ정보시스템공학과"),
MECHANICAL_ENGINEERING(Department.ENGINEERING, "기계공학부"),
MATERIALS_SCIENCE(Department.ENGINEERING, "신소재공학과"),

// IT대학
SW(Department.IT, "소프트웨어학부"),
GM(Department.IT, "글로벌미디어학과"),
GM(Department.IT, "글로벌미디어학부"),
COM(Department.IT, "컴퓨터학부"),
EE(Department.IT, "전자정보공학부"),
IP(Department.IT, "정보보호학과"),
AI(Department.IT, "AI융합학과"),
MB(Department.IT, "미디어경영학과");
AI(Department.IT, "AI융합학부"),
MB(Department.IT, "미디어경영학과"),

// 자유전공학부
LIBERAL_ARTS(Department.LIBERAL_ARTS, "자유전공학부");

private final Department department;
private final String displayName;
Expand Down