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
31 changes: 31 additions & 0 deletions src/main/java/com/example/fixlog/config/SecurityConfig.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package com.example.fixlog.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

@Configuration
public class SecurityConfig {

@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.csrf(csrf -> csrf.disable())
.authorizeHttpRequests(auth -> auth
.requestMatchers(HttpMethod.POST, "/api/members/signup").permitAll()
.requestMatchers(HttpMethod.GET, "/api/members/check-email").permitAll()
.requestMatchers(HttpMethod.GET, "/api/members/check-nickname").permitAll()
.anyRequest().authenticated()
);
return http.build();
}

@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package com.example.fixlog.controller.member;


import com.example.fixlog.dto.Response;
import com.example.fixlog.dto.member.SignupRequestDto;
import com.example.fixlog.dto.member.DuplicateCheckResponseDto;
import com.example.fixlog.service.member.MemberService;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/api/members")
@RequiredArgsConstructor
public class MemberController {

private final MemberService memberService;

@PostMapping("/signup")
public ResponseEntity<Response<String>> signup(@RequestBody SignupRequestDto request) {
memberService.signup(request);
return ResponseEntity.ok(Response.success("회원가입이 완료되었습니다.", null));
}

@GetMapping("/check-email")
public ResponseEntity<Response<DuplicateCheckResponseDto>> checkEmail(@RequestParam String email) {
boolean exists = memberService.isEmailDuplicated(email);
String msg = exists ? "이미 사용 중인 이메일입니다." : "사용 가능한 이메일입니다.";
return ResponseEntity.ok(Response.success(msg, new DuplicateCheckResponseDto(exists)));
}

@GetMapping("/check-nickname")
public ResponseEntity<Response<DuplicateCheckResponseDto>> checkNickname(@RequestParam String nickname) {
boolean exists = memberService.isNicknameDuplicated(nickname);
String msg = exists ? "이미 사용 중인 닉네임입니다." : "사용 가능한 닉네임입니다.";
return ResponseEntity.ok(Response.success(msg, new DuplicateCheckResponseDto(exists)));
}
}
12 changes: 11 additions & 1 deletion src/main/java/com/example/fixlog/domain/member/Member.java
Original file line number Diff line number Diff line change
Expand Up @@ -42,18 +42,28 @@ public class Member {
private SocialType socialType = SocialType.EMAIL;

@CreatedDate
@Column(updatable = false)
private LocalDateTime createdAt;

@LastModifiedDate
@Column
private LocalDateTime updatedAt;

// 프로필 사진 url, 지금은 nullable 이지만 나중에 기본값 설정
@Column
private String profileImageUrl;

@Column(length = 200)
private String bio;

@OneToMany(mappedBy = "member", cascade = CascadeType.ALL, orphanRemoval = true)
private List<Post> posts = new ArrayList<>();

// 북마크 폴더
// 북마크 폴더
@OneToMany(mappedBy = "owner", cascade = CascadeType.ALL, orphanRemoval = true)
private List<BookmarkFolder> bookmarkFolders = new ArrayList<>();

// Member 객체를 정적 팩토리 방식으로 회원가입 시에 생성하는 메서드
// Member 객체를 정적 팩토리 방식으로 생성하는 메서드
// Creates a Member object using a static factory method
public static Member of(String email, String password, String nickname, SocialType socialType) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.example.fixlog.dto.member;

import lombok.AllArgsConstructor;
import lombok.Getter;

@Getter
@AllArgsConstructor
public class DuplicateCheckResponseDto {
private boolean duplicated;
}
13 changes: 13 additions & 0 deletions src/main/java/com/example/fixlog/dto/member/SignupRequestDto.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.example.fixlog.dto.member;

import lombok.Getter;
import lombok.Setter;

@Getter
@Setter
public class SignupRequestDto {
private String email;
//비밀번호 재확인은 프론트단에서 확인
private String password;
private String nickname;
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ public enum ErrorCode {
CANNOT_UNFOLLOW_SELF(HttpStatus.BAD_REQUEST, "자기 자신은 언팔로우할 수 없습니다"),
ALREADY_FOLLOWING(HttpStatus.CONFLICT, "이미 팔로우 중입니다"),
FOLLOW_NOT_FOUND(HttpStatus.NOT_FOUND, "팔로우 관계가 존재하지 않습니다"),
ID_DUPLICATED(HttpStatus.CONFLICT, "중복된 아이디입니다"),
EMAIL_DUPLICATED(HttpStatus.CONFLICT, "중복된 이메일입니다"),
NICKNAME_DUPLICATED(HttpStatus.CONFLICT, "중복된 닉네임입니다"),
USER_ID_NOT_FOUND(HttpStatus.NOT_FOUND,"존재하지 않는 사용자 아이디입니다."),
POST_NOT_FOUND(HttpStatus.NOT_FOUND, "존재하지 않는 게시글입니다.");

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@

public interface MemberRepository extends JpaRepository<Member, Long> {
Optional<Member> findByEmail(String email); // 이메일로 회원 조회
Optional<Member> findByNickname(String nickname);
}
49 changes: 49 additions & 0 deletions src/main/java/com/example/fixlog/service/member/MemberService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package com.example.fixlog.service.member;

import com.example.fixlog.domain.member.Member;
import com.example.fixlog.domain.member.SocialType;
import com.example.fixlog.dto.member.SignupRequestDto;
import com.example.fixlog.exception.CustomException;
import com.example.fixlog.exception.ErrorCode;
import com.example.fixlog.repository.MemberRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

@Service
@RequiredArgsConstructor
public class MemberService {

private final MemberRepository memberRepository;
private final PasswordEncoder passwordEncoder;

public void signup(SignupRequestDto request) {
// 이메일 중복 검사
if (isEmailDuplicated(request.getEmail())) {
throw new CustomException(ErrorCode.EMAIL_DUPLICATED);
}

// 닉네임 중복 검사
if (isNicknameDuplicated(request.getNickname())) {
throw new CustomException(ErrorCode.NICKNAME_DUPLICATED);
}

// 문제 없으면 저장
Member member = Member.of(
request.getEmail(),
passwordEncoder.encode(request.getPassword()),
request.getNickname(),
SocialType.EMAIL
);

memberRepository.save(member);
}

public boolean isEmailDuplicated(String email) {
return memberRepository.findByEmail(email).isPresent();
}

public boolean isNicknameDuplicated(String nickname) {
return memberRepository.findByNickname(nickname).isPresent();
}
}
6 changes: 5 additions & 1 deletion src/main/resources/application.properties
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,8 @@ spring.datasource.password=

spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=update
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.H2Dialect
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.H2Dialect

# JWT
jwt.secret-key=fixlogfixlogfixlogfixlogfixlog1234
jwt.expiration-time=86400000