Skip to content

Commit

Permalink
refactor: 회원가입 시 이메일 형식 제한 제거 (#65) (#66)
Browse files Browse the repository at this point in the history
* chore: cors origin 세팅

* chore: 테스트 코드 내 불필요 코드 삭제

* chore: 불필요 코드 삭제

* refactor: 회원가입시 모든 이메일 입력가능

* test: 테스트 데이터 사입 SQL 변경
  • Loading branch information
kckc0608 authored Feb 10, 2025
1 parent 302de7f commit fe40e97
Show file tree
Hide file tree
Showing 13 changed files with 83 additions and 51 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
import com.keunsori.keunsoriserver.domain.member.domain.vo.MemberStatus;
import com.keunsori.keunsoriserver.global.exception.MemberException;
import jakarta.persistence.*;

import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

Expand All @@ -26,7 +28,7 @@ public class Member extends BaseEntity {
private String studentId;

@Column(length = 50)
private String hongikgmail;
private String email;

@Column(length = 200)
private String password;
Expand All @@ -40,9 +42,10 @@ public class Member extends BaseEntity {

private LocalDateTime approvalDate;

public Member(String studentId, String hongikgmail, String password, String name, MemberStatus status) {
@Builder
public Member(String studentId, String email, String password, String name, MemberStatus status) {
this.studentId = studentId;
this.hongikgmail = hongikgmail;
this.email = email;
this.password = password;
this.name = name;
this.status = status;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,7 @@
public interface MemberRepository extends JpaRepository<Member, Long> {
Optional<Member> findByStudentId(String studentId);
boolean existsByStudentId(String studentId);
Optional<Member> findByHongikgmail(String hongikgmail);
boolean existsByHongikgmail(String hongikgmail);
boolean existsByEmail(String email);

List<Member> findAllByStatus(MemberStatus status);
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,22 +10,20 @@
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import lombok.RequiredArgsConstructor;

@RestController
@RequiredArgsConstructor
@RequestMapping("/signup")
public class SignUpController {

private final SignUpService signUpService;

public SignUpController(SignUpService signUpService) {
this.signUpService = signUpService;
}

@PostMapping
public ResponseEntity<SignUpResponse> registerMember(@Valid @RequestBody SignUpRequest signUpRequest) {

//멤버 엔티티 빌드
SignUpResponse response=signUpService.registerMember(signUpRequest);
SignUpResponse response = signUpService.registerMember(signUpRequest);
return ResponseEntity.ok(response);

}
}
Original file line number Diff line number Diff line change
@@ -1,21 +1,25 @@
package com.keunsori.keunsoriserver.domain.member.sign_up.dto.request;

import jakarta.validation.constraints.Email;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Pattern;

import com.keunsori.keunsoriserver.domain.member.domain.Member;
import com.keunsori.keunsoriserver.domain.member.domain.vo.MemberStatus;


public record SignUpRequest(
@NotBlank(message = "이름은 필수 입력값입니다.")
@Pattern(regexp="[가-힣]{1,6}$", message = "이름은 6자 이하로 입력해주세요.")
@Pattern(regexp="[가-힣]{1,6}$", message = "이름은 한글 6자 이하로 입력해주세요.")
String name,

@NotBlank(message = "학번은 필수 입력값입니다.")
@Pattern(regexp="^[a-zA-Z][0-9]{6}", message="학번을 제대로 입력해주세요.")
String studentId,

@NotBlank(message="홍익대학교 이메일은 필수 입력값입니다.")
@Pattern(regexp="^.{1,}@g\\.hongik\\.ac\\.kr$",message="이메일은 학생이메일입니다. ex)[email protected]")
String hongikgmail,
@NotBlank(message="이메일은 필수 입력값입니다.")
@Email(message = "이메일 형식이 올바르지 않습니다.")
String email,

@NotBlank(message = "비밀번호는 필수 입력값입니다.")
@Pattern(regexp="^(?=.*[!@#$%^&*(),.?\":{}|<>])[a-zA-Z0-9!@#$%^&*(),.?\":{}|<>]{8,25}$",message="비밀번호는 특수문자, 영문자, 숫자를 포함한 8자리 이상 문자열입니다.")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@

public record SignUpResponse(String name,
String studentId,
String hongikgmail) {}
String email) {}
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
package com.keunsori.keunsoriserver.domain.member.sign_up.service;

import static com.keunsori.keunsoriserver.global.exception.ErrorMessage.DUPLICATED_EMAIL;
import static com.keunsori.keunsoriserver.global.exception.ErrorMessage.DUPLICATED_STUDENT_ID;
import static com.keunsori.keunsoriserver.global.exception.ErrorMessage.PASSWORD_IS_DIFFERENT_FROM_CHECK;

import com.keunsori.keunsoriserver.domain.member.domain.Member;
import com.keunsori.keunsoriserver.domain.member.repository.MemberRepository;
import com.keunsori.keunsoriserver.domain.member.domain.vo.MemberStatus;
Expand All @@ -14,38 +18,38 @@
@Service
@RequiredArgsConstructor
public class SignUpService {

private final MemberRepository memberRepository;
private final PasswordEncoder passwordEncoder;

@Transactional
public SignUpResponse registerMember(SignUpRequest signUpRequest) {
//학번 중복체크
final boolean validStudentId=memberRepository.existsByStudentId(signUpRequest.studentId());
if(validStudentId) {
throw new MemberException("이미 가입된 학번입니다.");
final boolean isDuplicatedStudentId = memberRepository.existsByStudentId(signUpRequest.studentId());
if (isDuplicatedStudentId) {
throw new MemberException(DUPLICATED_STUDENT_ID);
}


//이메일 중복체크
final boolean validHongikGmail= memberRepository.existsByHongikgmail(signUpRequest.hongikgmail());
if(validHongikGmail) {
throw new MemberException("이미 가입된 이메일 주소입니다.");
final boolean isDuplicatedEmail = memberRepository.existsByEmail(signUpRequest.email());
if (isDuplicatedEmail) {
throw new MemberException(DUPLICATED_EMAIL);
}

//비밀번호, 비밀번호 확인 일치하는지 확인
if(!signUpRequest.password().equals(signUpRequest.passwordConfirm())) {
throw new MemberException("비밀번호가 일치하지 않습니다. 다시 입력해주세요");
throw new MemberException(PASSWORD_IS_DIFFERENT_FROM_CHECK);
}

//비밀번호 암호화
String encodePassword = passwordEncoder.encode(signUpRequest.password());

//암호화된 비밀번호로 새로운 member 생성
Member member=new Member(signUpRequest.studentId(), signUpRequest.hongikgmail(), encodePassword, signUpRequest.name(), MemberStatus.승인대기);
Member member = new Member(signUpRequest.studentId(), signUpRequest.email(), encodePassword, signUpRequest.name(), MemberStatus.승인대기);

//Member 저장
Member savedMember=memberRepository.save(member);
Member savedMember = memberRepository.save(member);

return new SignUpResponse(savedMember.getName(), savedMember.getStudentId(), savedMember.getHongikgmail());
};
return new SignUpResponse(savedMember.getName(), savedMember.getStudentId(), savedMember.getEmail());
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
package com.keunsori.keunsoriserver.global.config;

import static com.keunsori.keunsoriserver.global.constant.EnvironmentConstant.DEV_URL;
import static com.keunsori.keunsoriserver.global.constant.EnvironmentConstant.LOCAL_URL_1;
import static com.keunsori.keunsoriserver.global.constant.EnvironmentConstant.LOCAL_URL_2;
import static com.keunsori.keunsoriserver.global.constant.EnvironmentConstant.LOCAL_URL_3;
import static com.keunsori.keunsoriserver.global.constant.EnvironmentConstant.PROD_URL;
import static org.springframework.http.HttpHeaders.SET_COOKIE;
import static org.springframework.security.config.Customizer.withDefaults;

Expand All @@ -14,6 +19,7 @@
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
Expand All @@ -39,7 +45,7 @@ public PasswordEncoder passwordEncoder() {
public SecurityFilterChain filterChain(HttpSecurity http, JwtAuthenticationFilter jwtAuthenticationFilter) throws Exception {
http
.cors(withDefaults())
.csrf(csrf -> csrf.disable()) // CSRF 비활성화
.csrf(AbstractHttpConfigurer::disable) // CSRF 비활성화
.sessionManagement(session -> session
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) // 세션 사용 안함
.authorizeHttpRequests(auth -> auth
Expand Down Expand Up @@ -68,13 +74,13 @@ public CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();

configuration.setAllowedOriginPatterns(List.of(
"*"
LOCAL_URL_1, LOCAL_URL_2, LOCAL_URL_3, DEV_URL, PROD_URL
));

configuration.addAllowedHeader("*");
configuration.addAllowedMethod("*");
//configuration.setAllowCredentials(true);
configuration.addExposedHeader(SET_COOKIE);
configuration.setAllowCredentials(true);
// configuration.addExposedHeader(SET_COOKIE);
configuration.addExposedHeader("Refresh-Token");

UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,22 +1,26 @@
package com.keunsori.keunsoriserver.global.config;

import static com.keunsori.keunsoriserver.global.constant.EnvironmentConstant.DEV_URL;
import static com.keunsori.keunsoriserver.global.constant.EnvironmentConstant.LOCAL_URL_1;
import static com.keunsori.keunsoriserver.global.constant.EnvironmentConstant.LOCAL_URL_2;
import static com.keunsori.keunsoriserver.global.constant.EnvironmentConstant.LOCAL_URL_3;
import static com.keunsori.keunsoriserver.global.constant.EnvironmentConstant.PROD_URL;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class WebConfig implements WebMvcConfigurer {

@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")
//.allowedMethods("GET","POST","PUT","DELETE", "OPTIONS")
.allowedMethods("*")
//.allowedHeaders("Authorization", "Content-Type")
.allowedHeaders("*")
.exposedHeaders("Refresh-Token")
//.allowCredentials("true")->도메인 정해지면 활성화
.maxAge(3600);
}
// @Override
// public void addCorsMappings(CorsRegistry registry) {
// registry.addMapping("/**")
// .allowedOrigins(LOCAL_URL_1, LOCAL_URL_2, LOCAL_URL_3, DEV_URL, PROD_URL)
// .allowedMethods("*")
// .allowedHeaders("*")
// .exposedHeaders("Refresh-Token")
// .allowCredentials(true)
// .maxAge(3600);
// }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.keunsori.keunsoriserver.global.constant;

public class EnvironmentConstant {

public static final String LOCAL_URL_1 = "http://localhost:5173";
public static final String LOCAL_URL_2 = "http://localhost:5174";
public static final String LOCAL_URL_3 = "http://localhost:8080";

public static final String DEV_URL = "https://keun-develop.vercel.app";

public static final String PROD_URL = "https://keun-sori-web.vercel.app";
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
public class ErrorMessage {
// Member
public static final String MEMBER_NOT_EXISTS_WITH_STUDENT_ID = "해당 학번을 가진 멤버가 존재하지 않습니다.";
public static final String DUPLICATED_STUDENT_ID = "이미 존재하는 학번입니다.";
public static final String DUPLICATED_EMAIL = "이미 존재하는 이메일입니다.";
public static final String PASSWORD_IS_DIFFERENT_FROM_CHECK = "비밀번호와 비밀번호 확인 입력값이 다릅니다.";

// Admin Member
public static final String INVALID_STATUS_FOR_APPROVAL = "회원이 승인 대기 상태가 아닙니다.";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
import static org.springframework.http.HttpHeaders.CONTENT_TYPE;

import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,16 +36,16 @@ public void findTableNames() {
}

@Override
public void afterPropertiesSet() throws Exception {
public void afterPropertiesSet() {
findTableNames();
}

private void truncate() {
em.createNativeQuery(String.format("SET FOREIGN_KEY_CHECKS = 0")).executeUpdate();
em.createNativeQuery("SET FOREIGN_KEY_CHECKS = 0").executeUpdate();
for (String tableName : tableNames) {
em.createNativeQuery("truncate table " + tableName).executeUpdate();
}
em.createNativeQuery(String.format("SET FOREIGN_KEY_CHECKS = 1")).executeUpdate();
em.createNativeQuery("SET FOREIGN_KEY_CHECKS = 1").executeUpdate();
}

@Transactional
Expand Down
6 changes: 3 additions & 3 deletions src/test/resources/import.sql
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
INSERT INTO member (member_id, create_date, update_date, approval_date, hongikgmail, name, password, status, student_id) VALUES (1, '2025-01-24 17:13:21.229103', '2025-01-24 17:13:21.229103', null, '[email protected]', '권찬', '$2a$10$dwQMaJPc5PKzS6w4I8Wi..DAYEkOKb7PSoeF9gplcfDzMWcC2k2eq', '일반', 'C011013');
INSERT INTO member (member_id, create_date, update_date, approval_date, hongikgmail, name, password, status, student_id) VALUES (2, '2025-01-25 03:16:36.414396', '2025-01-25 03:16:36.414396', null, '[email protected]', '권찬', '$2a$10$ED7kelp/IBsvNtvHVv/CfeWtQN.vymhDfTPYD50jKYvmxXn5c87im', '일반', 'C011014');
INSERT INTO member (member_id, create_date, update_date, approval_date, hongikgmail, name, password, status, student_id) VALUES (3, '2025-01-25 13:31:43.977683', '2025-01-25 13:31:43.977683', null, '[email protected]', '관리자', '$2a$10$XyBz6shlUlVC7HiKckWHX.wsstjTy19Y239VuK.wuZXwdDLH4lDHy', '관리자', 'Z011000');
INSERT INTO member (member_id, create_date, update_date, approval_date, email, name, password, status, student_id) VALUES (1, '2025-01-24 17:13:21.229103', '2025-01-24 17:13:21.229103', null, '[email protected]', '권찬', '$2a$10$dwQMaJPc5PKzS6w4I8Wi..DAYEkOKb7PSoeF9gplcfDzMWcC2k2eq', '일반', 'C011013');
INSERT INTO member (member_id, create_date, update_date, approval_date, email, name, password, status, student_id) VALUES (2, '2025-01-25 03:16:36.414396', '2025-01-25 03:16:36.414396', null, '[email protected]', '권찬', '$2a$10$ED7kelp/IBsvNtvHVv/CfeWtQN.vymhDfTPYD50jKYvmxXn5c87im', '일반', 'C011014');
INSERT INTO member (member_id, create_date, update_date, approval_date, email, name, password, status, student_id) VALUES (3, '2025-01-25 13:31:43.977683', '2025-01-25 13:31:43.977683', null, '[email protected]', '관리자', '$2a$10$XyBz6shlUlVC7HiKckWHX.wsstjTy19Y239VuK.wuZXwdDLH4lDHy', '관리자', 'Z011000');


-- INSERT INTO reservation (reservation_id, reservation_date, reservation_end_time, reservation_type, reservation_session, reservation_start_time, member_id) VALUES (1, '2025-01-01', '22:00:00', 'PERSONAL', 'VOCAL', '21:00:00', 1);
Expand Down

0 comments on commit fe40e97

Please sign in to comment.