Skip to content

Commit

Permalink
Merge pull request #37 from Likelion12/5-be-회원가입구현
Browse files Browse the repository at this point in the history
Feat : 회원가입 구현
  • Loading branch information
SonMyeongJin authored Aug 1, 2024
2 parents 982fb4e + 928ecda commit 24f20bd
Show file tree
Hide file tree
Showing 33 changed files with 214 additions and 16 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
HELP.md
build/
/.gradle
.gradle/
!gradle/wrapper/gradle-wrapper.jar
!**/src/main/**/build/
!**/src/test/**/build/
Expand Down
Binary file removed .gradle/8.9/checksums/checksums.lock
Binary file not shown.
Binary file removed .gradle/8.9/checksums/md5-checksums.bin
Binary file not shown.
Binary file removed .gradle/8.9/checksums/sha1-checksums.bin
Binary file not shown.
Empty file.
Binary file removed .gradle/8.9/executionHistory/executionHistory.bin
Binary file not shown.
Binary file removed .gradle/8.9/executionHistory/executionHistory.lock
Binary file not shown.
Binary file removed .gradle/8.9/fileChanges/last-build.bin
Binary file not shown.
Binary file removed .gradle/8.9/fileHashes/fileHashes.bin
Binary file not shown.
Binary file removed .gradle/8.9/fileHashes/fileHashes.lock
Binary file not shown.
Binary file removed .gradle/8.9/fileHashes/resourceHashesCache.bin
Binary file not shown.
Empty file removed .gradle/8.9/gc.properties
Empty file.
Binary file removed .gradle/buildOutputCleanup/buildOutputCleanup.lock
Binary file not shown.
2 changes: 0 additions & 2 deletions .gradle/buildOutputCleanup/cache.properties

This file was deleted.

Binary file removed .gradle/buildOutputCleanup/outputFiles.bin
Binary file not shown.
Binary file removed .gradle/file-system.probe
Binary file not shown.
Empty file removed .gradle/vcs-1/gc.properties
Empty file.
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;

@SpringBootApplication
@EnableJpaRepositories
@EnableJpaAuditing
public class Likelion12Application {

public static void main(String[] args) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.example.likelion12.common.exception;

import com.example.likelion12.common.response.status.ResponseStatus;
import lombok.Getter;

@Getter
public class ExerciseException extends RuntimeException{

private final ResponseStatus exceptionStatus;

public ExerciseException(ResponseStatus exceptionStatus) {
super(exceptionStatus.getMessage());
this.exceptionStatus = exceptionStatus;
}

public ExerciseException(ResponseStatus exceptionStatus, String message) {
super(message);
this.exceptionStatus = exceptionStatus;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package com.example.likelion12.common.exception_handler;

import com.example.likelion12.common.exception.ExerciseException;
import com.example.likelion12.common.response.BaseErrorResponse;
import jakarta.annotation.Priority;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;

@Slf4j
@Priority(0)
@RestControllerAdvice
public class ExerciseExceptionControllerAdvice {
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ExceptionHandler(ExerciseException.class)
public BaseErrorResponse handle_ExerciseException(ExerciseException e) {
log.error("[handle_ExerciseException]", e);
return new BaseErrorResponse(e.getExceptionStatus(), e.getMessage());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,17 @@ public enum BaseExceptionResponseStatus implements ResponseStatus{
* 1000: 요청 성공 (OK)
*/
SUCCESS(1000,HttpStatus.OK.value(), "요청에 성공하였습니다."),
FAILURE(2000, HttpStatus.BAD_REQUEST.value(), "요청에 실패하였습니다.");
FAILURE(2000, HttpStatus.BAD_REQUEST.value(), "요청에 실패하였습니다."),

/**
* 3000 : member 관련
*/
ALREADY_EXIST_EMAIL(3000, HttpStatus.BAD_REQUEST.value(), "이미 존재하는 이메일입니다."),

/**
* 4000 : exercise 관련
*/
CANNOT_FOUND_EXERCISE(4000, HttpStatus.BAD_REQUEST.value(), "조건에 맞는 exercise 객체를 찾을 수 없습니다.");


private final int code;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
.csrf(CsrfConfigurer<HttpSecurity>::disable)
.authorizeHttpRequests(requests ->
requests
.requestMatchers("/test", "/auth/kakao/callback").permitAll() // 이 URL은 모두에게 허용
.requestMatchers("/test", "/auth/kakao/callback", "/user/signup").permitAll() // 이 URL은 모두에게 허용
.anyRequest().authenticated() // 그 외의 모든 요청은 인증 필요
)
.sessionManagement(sessionManagement ->
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package com.example.likelion12.controller;

import com.example.likelion12.common.response.BaseResponse;
import com.example.likelion12.dto.PostSignupRequest;
import com.example.likelion12.dto.PostSignupResponse;
import com.example.likelion12.service.MemberService;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@Slf4j
@RestController
@AllArgsConstructor
@RequestMapping("/user")
public class MemberController {

private final MemberService memberService;

@PostMapping("/signup")
public BaseResponse<PostSignupResponse> signUp(@RequestBody PostSignupRequest postSignupRequest){
log.info("[MemberController.signUp]");
return new BaseResponse<>(memberService.signUp(postSignupRequest));
}
}
8 changes: 8 additions & 0 deletions src/main/java/com/example/likelion12/domain/Member.java
Original file line number Diff line number Diff line change
Expand Up @@ -59,4 +59,12 @@ public class Member extends BaseTime {
@JoinColumn(name = "exercise_id")
private Exercise exercise;

public Member(String memberName, String email, String memberImg, BaseGender gender, BaseStatus status, Exercise exercise){
this.memberName = memberName;
this.email = email;
this.memberImg = memberImg;
this.gender = gender;
this.status = status;
this.exercise = exercise;
}
}
18 changes: 18 additions & 0 deletions src/main/java/com/example/likelion12/dto/PostSignupRequest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.example.likelion12.dto;

import com.example.likelion12.domain.base.BaseGender;
import lombok.AllArgsConstructor;
import lombok.Getter;

@Getter
@AllArgsConstructor
public class PostSignupRequest {
/**
* 회원가입 request dto
*/
private String nickname;
private String profileImage;
private String email;
private BaseGender gender;
private String exercise;
}
14 changes: 14 additions & 0 deletions src/main/java/com/example/likelion12/dto/PostSignupResponse.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.example.likelion12.dto;

import lombok.AllArgsConstructor;
import lombok.Getter;

@Getter
@AllArgsConstructor
public class PostSignupResponse {
/**
* 회원가입 response dto
*/
private Long memberId;
private String accessToken;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.example.likelion12.repository;

import com.example.likelion12.domain.Exercise;
import com.example.likelion12.domain.base.BaseStatus;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

import java.util.Optional;

@Repository
public interface ExerciseRepository extends JpaRepository<Exercise, Long> {

Optional<Exercise> findByExerciseNameAndStatus(String exerciseName, BaseStatus status);
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,5 @@
public interface MemberRepository extends JpaRepository<Member, Long> {

Optional<Member> findByEmailAndStatus(String email, BaseStatus status);
boolean existsByEmailAndStatus(String email, BaseStatus status);
}
65 changes: 65 additions & 0 deletions src/main/java/com/example/likelion12/service/MemberService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package com.example.likelion12.service;

import com.example.likelion12.common.exception.ExerciseException;
import com.example.likelion12.common.exception.MemberException;
import com.example.likelion12.domain.Exercise;
import com.example.likelion12.domain.Member;
import com.example.likelion12.domain.base.BaseGender;
import com.example.likelion12.domain.base.BaseStatus;
import com.example.likelion12.dto.PostSignupRequest;
import com.example.likelion12.dto.PostSignupResponse;
import com.example.likelion12.repository.ExerciseRepository;
import com.example.likelion12.repository.MemberRepository;
import com.example.likelion12.util.JwtProvider;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import static com.example.likelion12.common.response.status.BaseExceptionResponseStatus.ALREADY_EXIST_EMAIL;
import static com.example.likelion12.common.response.status.BaseExceptionResponseStatus.CANNOT_FOUND_EXERCISE;

@Slf4j
@Service
@RequiredArgsConstructor
@Transactional(readOnly = true)
public class MemberService {

private final MemberRepository memberRepository;
private final ExerciseRepository exerciseRepository;
private final JwtProvider jwtProvider;
private final TokenService tokenService;

/**
* 회원가입
*/
@Transactional
public PostSignupResponse signUp(PostSignupRequest postSignupRequest){
log.info("[MemberService.signUp]");
String nickname = postSignupRequest.getNickname();
String profileImage = postSignupRequest.getProfileImage();
String email = postSignupRequest.getEmail();
BaseGender gender = postSignupRequest.getGender();
String exerciseName = postSignupRequest.getExercise();

//동일한 이메일을 가지고 있는 회원이 있는지 확인
if(memberRepository.existsByEmailAndStatus(email, BaseStatus.ACTIVE)){
throw new MemberException(ALREADY_EXIST_EMAIL);
}else{
log.info("[MemberService.signUp] email 검증 완료");
// 운동명을 가지고 exercise 객체 찾기
Exercise exercise = exerciseRepository.findByExerciseNameAndStatus(exerciseName, BaseStatus.ACTIVE)
.orElseThrow(()-> new ExerciseException(CANNOT_FOUND_EXERCISE));

// 데이터베이스에 저장하기
Member member = new Member(nickname, email, profileImage, gender, BaseStatus.ACTIVE, exercise);
memberRepository.save(member);

// 토큰 발급, 레디스에 저장하기
String accessToken = jwtProvider.createAccessToken(email,member.getMemberId());
// 반환하기
tokenService.storeToken(accessToken,member.getMemberId());
return new PostSignupResponse(member.getMemberId(), accessToken);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ public class TokenService {

public void storeToken(String token, Long memberId) {
// redis 에 토큰 저장
log.info("[TokenService.storeToken]");
redisTemplate.opsForValue().set(String.valueOf(memberId), token, accessTokenExpiration, TimeUnit.MILLISECONDS);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ protected void doFilterInternal(HttpServletRequest request, HttpServletResponse
if (token != null) {
try {
log.info(token);
String memberId = String.valueOf(jwtProvider.extractIdFromHeader(token));
String memberId = String.valueOf(jwtProvider.extractMemberIdFromJwtToken(token));
if (tokenService.checkTokenExists(memberId)) { // 리프레시 토큰이 존재하는지 확인
Member member = new Member(Long.valueOf(memberId), null, null, null, null, null, null, null, null,null);
AbstractAuthenticationToken authenticated = new UsernamePasswordAuthenticationToken(member, null, null);
Expand All @@ -57,7 +57,7 @@ protected void doFilterInternal(HttpServletRequest request, HttpServletResponse
private String parseBearerToken(HttpServletRequest request) {
return Optional.ofNullable(request.getHeader(HttpHeaders.AUTHORIZATION))
.filter(token -> token.startsWith("Bearer "))
.map(token -> token.substring(7))
.map(token -> token.substring(7).trim()) // 공백 제거
.orElse(null);
}
}
12 changes: 5 additions & 7 deletions src/main/java/com/example/likelion12/util/JwtProvider.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import lombok.AllArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

Expand All @@ -22,15 +21,15 @@ public class JwtProvider {

// Access Token 생성
public String createAccessToken(String email, Long memberId) {
Claims claims = Jwts.claims().setSubject(email);
Claims claims = Jwts.claims().setSubject(email.trim());
Date now = new Date();
Date validity = new Date(now.getTime() + accessTokenExpiration);

return Jwts.builder()
.setClaims(claims)
.setIssuedAt(now)
.setExpiration(validity)
.claim("memberId",memberId)
.claim("memberId", memberId)
.signWith(SignatureAlgorithm.HS256, secretKey)
.compact();
}
Expand All @@ -52,7 +51,7 @@ public Long extractIdFromHeader(String authorization) {
try {
jwtToken = extractJwtToken(authorization);
} catch (IllegalArgumentException e) {
throw new IllegalArgumentException("유효하지 않은 헤더 포멧입니다.");
throw new IllegalArgumentException("유효하지 않은 헤더 포맷입니다.");
}

// JWT 토큰에서 사용자 정보 추출
Expand All @@ -71,9 +70,9 @@ public Long extractIdFromHeader(String authorization) {
public String extractJwtToken(String authorizationHeader) {
String[] parts = authorizationHeader.split(" ");
if (parts.length == 2) {
return parts[1]; // 토큰 부분 추출
return parts[1].trim(); // 토큰 부분 추출 및 공백 제거
}
throw new IllegalArgumentException("유효하지 않은 헤더 포멧입니다.");
throw new IllegalArgumentException("유효하지 않은 헤더 포맷입니다.");
}

public Long extractMemberIdFromJwtToken(String jwtToken) {
Expand All @@ -91,5 +90,4 @@ public Long extractMemberIdFromJwtToken(String jwtToken) {

return memberId;
}

}
3 changes: 2 additions & 1 deletion src/main/resources/application.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ spring:
registration:
kakao:
client-id: ${CLIENT_ID}
redirect-uri: "http://43.202.94.241:8080/auth/kakao/callback"
# redirect-uri: "http://43.202.94.241:8080/auth/kakao/callback"
redirect-uri: "http://localhost:8080/auth/kakao/callback"
---
jwt:
secret: ${JWT_SECRET}
Expand Down

0 comments on commit 24f20bd

Please sign in to comment.