Skip to content

Commit

Permalink
feat: Google OAuth 로그인 기능 추가
Browse files Browse the repository at this point in the history
  • Loading branch information
shinsj4653 committed Jan 16, 2024
1 parent a483521 commit 37aebaf
Show file tree
Hide file tree
Showing 13 changed files with 170 additions and 23 deletions.
53 changes: 53 additions & 0 deletions src/main/java/gdsc/pointer/controller/ControllerAdvice.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package gdsc.pointer.controller;

import gdsc.pointer.dto.response.error.ErrorResponse;
import gdsc.pointer.exception.PointerException;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import java.sql.SQLException;
import java.util.Objects;

@Slf4j
@RestControllerAdvice
public class ControllerAdvice {
private static final int FIELD_ERROR_CODE_INDEX = 0;
private static final int FIELD_ERROR_MESSAGE_INDEX = 1;

@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity<ErrorResponse> handleInputFieldException(MethodArgumentNotValidException e) {
FieldError mainError = e.getFieldErrors().get(0);
String[] errorInfo = Objects.requireNonNull(mainError.getDefaultMessage()).split(":");

int code = Integer.parseInt(errorInfo[FIELD_ERROR_CODE_INDEX]);
String message = errorInfo[FIELD_ERROR_MESSAGE_INDEX];

return ResponseEntity.badRequest().body(new gdsc.pointer.dto.response.error.ErrorResponse(code, message));
}

@ExceptionHandler(SQLException.class)
public ResponseEntity<ErrorResponse> sqlExceptionHandle(PointerException e) {
return ResponseEntity.status(e.getHttpStatus()).body(new ErrorResponse(e.getCode(), e.getMessage()));
}

@ExceptionHandler(PointerException.class)
public ResponseEntity<ErrorResponse> handleSubwayException(PointerException e) {
return ResponseEntity.status(e.getHttpStatus()).body(new ErrorResponse(e.getCode(), e.getMessage()));
}

@ExceptionHandler(Exception.class)
public ResponseEntity<ErrorResponse> unhandledException(Exception e, HttpServletRequest request) {
log.error("UnhandledException: {} {} errMessage={}\n",
request.getMethod(),
request.getRequestURI(),
e.getMessage()
);
return ResponseEntity.internalServerError()
.body(new ErrorResponse(9999, "일시적으로 접속이 원활하지 않습니다. 지하철 서비스 팀에 문의 부탁드립니다."));
}
}
9 changes: 7 additions & 2 deletions src/main/java/gdsc/pointer/controller/LoginController.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
package gdsc.pointer.controller;

import gdsc.pointer.dto.request.login.UserDto;
import gdsc.pointer.dto.response.ResultDto;
import gdsc.pointer.service.LoginService;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

@RestController
Expand All @@ -12,8 +16,9 @@ public class LoginController {
private final LoginService loginService;

@GetMapping("/code/{registrationId}")
public void googleLogin(@RequestParam String code, @PathVariable String registrationId) {
loginService.socialLogin(code, registrationId);
public ResponseEntity<?> googleLogin(@RequestParam String code, @PathVariable String registrationId) throws Exception {
UserDto userDto = loginService.socialLogin(code, registrationId);
return ResponseEntity.ok(ResultDto.res(HttpStatus.OK, "회원 가입 완료", userDto));
}

}
17 changes: 11 additions & 6 deletions src/main/java/gdsc/pointer/controller/UserController.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,19 +21,24 @@ public class UserController {
@GetMapping("getUsers")
public ResponseEntity<?> getUsers() throws Exception {
List<User> users = userService.getUsers();
return ResponseEntity.ok(ResultDto.res(HttpStatus.OK, "회원 조회 완료", users));
return ResponseEntity.ok(ResultDto.res(HttpStatus.OK, "모든 회원 조회 완료", users));
}
@GetMapping("/getUserDetail/{id}")
public ResponseEntity<?> getUserDetail(@PathVariable("id") String id) throws Exception{
User user = userService.getUserDetail(id);
if (user == null) {
return ResponseEntity.ok(ResultDto.res(HttpStatus.NOT_FOUND, "존재하지 않는 회원입니다.", null));
}
return ResponseEntity.ok(ResultDto.res(HttpStatus.OK, "회원 정보 조회 완료", user));
}

@PostMapping()
public ResponseEntity<?> addUser(@RequestBody UserDto userDto) throws Exception{
userService.addUser(userDto);
return ResponseEntity.ok(ResultDto.res(HttpStatus.CREATED, "회원 가입 완료"));
}
//
// @GetMapping("/getUserDetail")
// public ResponseEntity<?> getUserDetail(@RequestParam("id") String id) throws Exception{
// return userService.getUserDetail(id);
// }


//
// @PutMapping("/updateUser/{id}")
// public ResponseEntity<?> updateUser(@PathVariable("id") String id, @RequestBody User user) throws Exception{
Expand Down
23 changes: 18 additions & 5 deletions src/main/java/gdsc/pointer/dao/UserDao.java
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
package gdsc.pointer.dao;

import com.google.api.core.ApiFuture;
import com.google.cloud.firestore.Firestore;
import com.google.cloud.firestore.QueryDocumentSnapshot;
import com.google.cloud.firestore.QuerySnapshot;
import com.google.cloud.firestore.*;
import com.google.firebase.cloud.FirestoreClient;
import gdsc.pointer.domain.User;
import gdsc.pointer.dto.request.login.UserDto;
import gdsc.pointer.exception.notfound.user.UserNotFoundException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Repository;

import java.util.ArrayList;
Expand All @@ -31,11 +31,24 @@ public List<User> getUsers() throws Exception {
}



public User getUserDetail(String id) throws Exception {
Firestore firestore = FirestoreClient.getFirestore();
DocumentReference documentReference =
firestore.collection(COLLECTION_NAME).document(id);
ApiFuture<DocumentSnapshot> apiFuture = documentReference.get();
DocumentSnapshot documentSnapshot = apiFuture.get();
User user = null;
if(documentSnapshot.exists()){
user = documentSnapshot.toObject(User.class);
}
return user;
}


public void addUser(UserDto userDto) throws Exception {

Firestore firestore = FirestoreClient.getFirestore();
ApiFuture<com.google.cloud.firestore.WriteResult> apiFuture =
firestore.collection(COLLECTION_NAME).document(userDto.getId()).set(userDto);
}


Expand Down
2 changes: 1 addition & 1 deletion src/main/java/gdsc/pointer/domain/User.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
public class User {

private String id;
private String name;
private String email;
private String nickname;

}
4 changes: 4 additions & 0 deletions src/main/java/gdsc/pointer/dto/request/login/UserDto.java
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
package gdsc.pointer.dto.request.login;

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Getter
@NoArgsConstructor
@AllArgsConstructor
public class UserDto {
private String id;
private String email;
Expand Down
14 changes: 14 additions & 0 deletions src/main/java/gdsc/pointer/dto/response/error/ErrorResponse.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package gdsc.pointer.dto.response.error;

import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@AllArgsConstructor
public class ErrorResponse {
private int code;
private String message;
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@
public enum CustomExceptionContext implements ExceptionContext {

// BAD_REQUEST
DUPLICATE_USER_ID_ERROR("이미 구글 로그인을 통해 회원가입을 진행한 이력이 있습니다.", 1000);

DUPLICATE_USER_ID_ERROR("이미 구글 로그인을 통해 회원가입을 진행한 이력이 있습니다.", 1000),

// NOT_FOUND
USER_NOT_FOUND_ERROR("존재하지 않는 회원입니다.", 2000);

// UNAUTHORIZED
private final String message;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package gdsc.pointer.exception.notfound;

import gdsc.pointer.exception.ExceptionContext;
import gdsc.pointer.exception.PointerException;
import org.springframework.http.HttpStatus;

public class NotFoundException extends PointerException {
public NotFoundException(ExceptionContext context) {
super(HttpStatus.NOT_FOUND, context.getMessage(), context.getCode());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package gdsc.pointer.exception.notfound.user;

import gdsc.pointer.exception.notfound.NotFoundException;

import static gdsc.pointer.exception.CustomExceptionContext.USER_NOT_FOUND_ERROR;

public class UserNotFoundException extends NotFoundException {
public UserNotFoundException() {
super(USER_NOT_FOUND_ERROR);
}
}
23 changes: 16 additions & 7 deletions src/main/java/gdsc/pointer/service/LoginService.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

import com.fasterxml.jackson.databind.JsonNode;
import gdsc.pointer.dao.UserDao;
import gdsc.pointer.dto.request.login.UserDto;
import gdsc.pointer.exception.badrequest.user.DuplicateUserIdException;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
Expand Down Expand Up @@ -35,7 +37,7 @@ public class LoginService {
private final RestTemplate restTemplate = new RestTemplate();


public void socialLogin(String code, String registrationId) {
public UserDto socialLogin(String code, String registrationId) throws Exception {

String accessToken = getAccessToken(code, registrationId);
JsonNode userResourceNode = getUserResource(accessToken, registrationId);
Expand All @@ -50,15 +52,22 @@ public void socialLogin(String code, String registrationId) {

// 처음 로그인 하는 유저라면 Firebase DB에 정보 저장 O
// 이미 존재하는 유저의 id라면 DB에 정보 저장 X
if (validateDuplicateUser(id)) {
throw new DuplicateUserIdException();
}

validateDuplicateUser(id);

UserDto userDto = new UserDto(id, email, nickname);
userDao.addUser(userDto);
return userDto;
}

private void validateDuplicateUser(String id) {



private boolean validateDuplicateUser(String id) throws Exception {
if (userDao.getUserDetail(id) != null) {
// 이미 존재하는 유저인 경우
return true;
} else {
return false;
}
}

private String getAccessToken(String authorizationCode, String registrationId) {
Expand Down
2 changes: 2 additions & 0 deletions src/main/java/gdsc/pointer/service/UserService.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,7 @@

public interface UserService {
List<User> getUsers() throws Exception;

User getUserDetail(String id) throws Exception;
void addUser(UserDto userDto) throws Exception;
}
20 changes: 20 additions & 0 deletions src/main/java/gdsc/pointer/service/UserServiceImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,14 @@
import gdsc.pointer.dao.UserDao;
import gdsc.pointer.domain.User;
import gdsc.pointer.dto.request.login.UserDto;
import gdsc.pointer.exception.badrequest.user.DuplicateUserIdException;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.List;

@Slf4j
@Service
@RequiredArgsConstructor
public class UserServiceImpl implements UserService {
Expand All @@ -19,11 +22,28 @@ public List<User> getUsers() throws Exception {
return userDao.getUsers();
}

@Override
public User getUserDetail(String id) throws Exception {
return userDao.getUserDetail(id);
}


@Override
public void addUser(UserDto userDto) throws Exception {
if (validateDuplicateUser(userDto.getId())){
throw new DuplicateUserIdException();
}
userDao.addUser(userDto);
}

private boolean validateDuplicateUser(String id) throws Exception {
if (userDao.getUserDetail(id) != null) {
// 이미 존재하는 유저인 경우
return true;
} else {
return false;
}
}
//
// @Override
// public ResponseEntity<?> getUserDetail(String id) throws Exception {
Expand Down

0 comments on commit 37aebaf

Please sign in to comment.