Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(#6) : 회원가입, 로그인 및 토큰 처리 #8

Merged
merged 1 commit into from
Aug 18, 2024
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
2 changes: 2 additions & 0 deletions member-service/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,5 @@ out/

### VS Code ###
.vscode/

src/main/resources/application-prod.yml
6 changes: 4 additions & 2 deletions member-service/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -47,19 +47,21 @@ dependencies {
// model-mapper
implementation group: 'org.modelmapper', name: 'modelmapper', version: '2.3.8'

// redis
implementation 'org.springframework.boot:spring-boot-starter-data-redis'

implementation 'io.hypersistence:hypersistence-utils-hibernate-63:3.7.5'
implementation 'com.fasterxml.jackson.core:jackson-core:2.15.0'
implementation 'com.fasterxml.jackson.core:jackson-databind:2.15.0'

//google
// google
implementation 'org.springframework.boot:spring-boot-starter-oauth2-client'

runtimeOnly 'com.h2database:h2'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation 'org.springframework.security:spring-security-test'

//jwt
// jwt
runtimeOnly 'io.jsonwebtoken:jjwt-jackson:0.11.5'
runtimeOnly 'io.jsonwebtoken:jjwt-impl:0.11.5'
implementation 'io.jsonwebtoken:jjwt-api:0.11.5'
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package com.chuca.memberservice.domain.member.constant;

public enum MemberProvider {
APP, KAKAO, GOOGLE, NAVER
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package com.chuca.memberservice.domain.member.controller;

import com.chuca.memberservice.domain.member.dto.CheckDto;
import com.chuca.memberservice.domain.member.dto.LoginDto;
import com.chuca.memberservice.domain.member.dto.OAuthLoginDto;
import com.chuca.memberservice.domain.member.dto.SignUpDto;
import com.chuca.memberservice.domain.member.service.MemberService;
import com.chuca.memberservice.global.response.BaseResponse;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

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

private final MemberService memberService;

// 휴대전화 인증


// 아이디 중복 확인
@GetMapping("/check-id")
public ResponseEntity<BaseResponse<CheckDto.Response>> checkId(@RequestBody @Validated CheckDto.idRequest request) {
return ResponseEntity.ok(BaseResponse.create(memberService.checkId(request.getGeneralId())));
}

// 일반 회원가입
@PostMapping("/signup")
public ResponseEntity<BaseResponse<SignUpDto.Response>> signup(@RequestBody @Validated SignUpDto.Request request) { // 추후에 이미지도 처리 해야함
return ResponseEntity.ok(BaseResponse.create(memberService.signup(request)));
}

// 일반 로그인
@PostMapping("/login")
public ResponseEntity<BaseResponse<LoginDto.Response>> login(@RequestBody @Validated LoginDto.Request request) {
return ResponseEntity.ok(BaseResponse.create(memberService.login(request)));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
//package com.chuca.memberservice.domain.member.controller;
//
//import com.chuca.memberservice.domain.member.dto.OAuthLoginDto;
//import com.chuca.memberservice.domain.member.service.oauth.KakaoOauthService;
//import com.chuca.memberservice.domain.member.service.oauth.NaverOauthService;
//import com.chuca.memberservice.global.response.BaseResponse;
//import com.fasterxml.jackson.core.JsonProcessingException;
//import lombok.RequiredArgsConstructor;
//import org.springframework.http.ResponseEntity;
//import org.springframework.web.bind.annotation.*;
//
//import java.io.IOException;
//
//@RestController
//@RequestMapping("/oauth")
//@RequiredArgsConstructor
//public class OAuthController {
//
// private final NaverOauthService naverOauthService;
// private final KakaoOauthService kakaoOauthService;
//
// // 1. 네이버 로그인 (사용자 로그인 페이지 제공 단계)
// @GetMapping("/{socialType}")
// public void naverLogin(@PathVariable("socialType") String provider) throws IOException {
// naverOauthService.request();
// }
//
// // 2. 네이버 로그인 (사용자 정보 받기)
// @GetMapping("/{socialType}/callback")
// public ResponseEntity<BaseResponse<OAuthLoginDto.Response>> callback(
// @PathVariable("socialType") String provider,
// @RequestParam String code,
// @RequestParam String state) throws JsonProcessingException {
// return ResponseEntity.ok(BaseResponse.create(naverOauthService.login(code, state)));
// }
//
// // 3. 카카오 로그인 및 회원가입 (기획 로직 수정 중이라 추후에 약관 관련한 처리해야하고, 사업자 정보 발급하면 전화번호도 받아오기)
// @PostMapping("/{socialType}")
// public ResponseEntity<BaseResponse<OAuthLoginDto.Response>> kakaoLogin(@PathVariable("socialType") String provider, @RequestBody OAuthLoginDto.Request request) {
// return ResponseEntity.ok(BaseResponse.create(kakaoOauthService.kakaoLogin(request)));
// }
//}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.chuca.memberservice.domain.member.controller;

import com.chuca.memberservice.domain.member.entity.Member;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@Slf4j
@RestController
public class TestController {

@GetMapping("/test")
public String test() {
return "Hello, World!";
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package com.chuca.memberservice.domain.member.dto;

import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.Pattern;
import lombok.*;

public class CheckDto {

@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@AllArgsConstructor
@Builder
public static class idRequest {
@NotEmpty
private String generalId;
}

@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@AllArgsConstructor
@Builder
public static class Response {
private boolean check;
}

@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@AllArgsConstructor
@Builder
public static class nicknameRequest {
@NotEmpty
private String nickname;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package com.chuca.memberservice.domain.member.dto;

import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.Pattern;
import lombok.*;

public class LoginDto {

@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@AllArgsConstructor
@Builder
public static class Request {
@NotEmpty
private String generalId;

@Pattern(regexp = "^(?=.*[A-Za-z])(?=.*\\d)(?=.*[$@$!%*#?&])[A-Za-z\\d$@$!%*#?&]{8,20}$", message = "비밀번호는 8자 이상 대문자, 소문자, 숫자, 특수문자 등 3가지 이상을 사용해 주세요.")
private String password;
}

@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@AllArgsConstructor
@Builder
public static class Response {
private String accessToken;
private String refreshToken;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package com.chuca.memberservice.domain.member.dto;

import lombok.*;

public class OAuthLoginDto {
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@AllArgsConstructor
@Builder
public static class Request {
private String email;
private String nickname;
private String profileImage;
}

@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@AllArgsConstructor
@Builder
public static class Response {
private String accessToken;
private String refreshToken;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package com.chuca.memberservice.domain.member.dto;

public class PhoneDto {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package com.chuca.memberservice.domain.member.dto;

import jakarta.persistence.Column;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Pattern;
import lombok.*;

public class SignUpDto {

@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@AllArgsConstructor
@Builder
public static class Request {
@NotEmpty
private String generalId;

@NotEmpty
@Pattern(regexp = "^(?=.*[A-Za-z])(?=.*\\d)(?=.*[$@$!%*#?&])[A-Za-z\\d$@$!%*#?&]{8,20}$", message = "비밀번호는 8자 이상 대문자, 소문자, 숫자, 특수문자 등 3가지 이상을 사용해 주세요.")
private String password;

@NotEmpty
private String phone;

@NotNull
private boolean locTos; // 위치 기반 서비스 이용약관 동의 여부

@NotNull
private boolean adTos; // 광고성 정보 수신 동의 여부

@NotEmpty
private String nickname;

private String profileImage; // 추후에 이미지 관련 처리해야함
}

@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@AllArgsConstructor
@Builder
public static class Response {
private String accessToken;
private String refreshToken;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
package com.chuca.memberservice.domain.member.entity;

import com.chuca.memberservice.domain.member.constant.MemberProvider;
import com.chuca.memberservice.global.entity.BaseTime;
import io.hypersistence.utils.hibernate.type.json.JsonType;
import jakarta.persistence.*;
import lombok.*;
import org.hibernate.annotations.ColumnDefault;
import org.hibernate.annotations.DynamicInsert;
import org.hibernate.annotations.DynamicUpdate;
import org.hibernate.annotations.Type;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;

import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;

@Getter
@AllArgsConstructor
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@DynamicInsert
@DynamicUpdate
@Entity
@Table(name = "member")
public class Member extends BaseTime implements UserDetails {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "memberId")
private Long id;

// 일반 로그인 시 필요한 아이디 (일반 로그인에만 사용)
@Column(nullable = true, unique = true)
private String generalId;

@Column(unique = true)
private String email; // 이메일 (소셜 로그인에만 사용)

@Column(unique = true)
private String password;

@Enumerated(EnumType.STRING)
@ColumnDefault("'APP'")
private MemberProvider provider;

private String phone;

@Column(nullable = false)
private boolean locTos; // 위치 기반 서비스 이용약관 동의 여부

@Column(nullable = false)
private boolean adTos; // 광고성 정보 수신 동의 여부

@Column(nullable = false, unique = true)
private String nickname;

private String profileImage; // 프로필 이미지

@Column(nullable = false)
@ColumnDefault("'active'")
private String status;

@Type(JsonType.class)
@Column(name = "alarms", columnDefinition = "longtext")
private Map<String, Object> alarms = new LinkedHashMap<>(); // 알림 설정 (관심 키워드, 관심 카페, 연락, 야간 푸시 알림)\

// 소셜 로그인 시 활용
@Builder
public Member(String email, MemberProvider provider, String phone, String nickname, String profileImage) {
Map<String, Object> settings = new LinkedHashMap<>();
settings.put("option1", true); // 관심 키워드
settings.put("option2", true); // 관심 카페
settings.put("option3", true); // 연락
settings.put("option4", true); // 야간 푸시 알림

this.email = email;
this.provider = provider;
this.phone = phone;
this.nickname = nickname;
this.profileImage = profileImage != null ? profileImage : "";
this.locTos = false;
this.adTos = false;
this.alarms = settings;
}

// 일반 로그인 시 활용
public Member(String gerneralId, String password, String phone, boolean locTos, boolean adTos, String nickname, String profileImage) {
Map<String, Object> settings = new LinkedHashMap<>();
settings.put("option1", true); // 관심 키워드
settings.put("option2", true); // 관심 카페
settings.put("option3", true); // 연락
settings.put("option4", true); // 야간 푸시 알림

this.generalId = gerneralId;
this.password = password;
this.phone = phone;
this.locTos = locTos;
this.adTos = adTos;
this.nickname = nickname;
this.profileImage = profileImage != null ? profileImage : "";
this.alarms = settings;
}

@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return null;
}

@Override
public String getUsername() {
return null;
}
}
Loading