Skip to content

Commit

Permalink
Merge pull request #73 from skawnkk/be/feature/oauth
Browse files Browse the repository at this point in the history
OAuth 로그인 기능 구현
  • Loading branch information
eNoLJ authored Apr 30, 2021
2 parents ea963cc + 73b2daf commit 2266a10
Show file tree
Hide file tree
Showing 10 changed files with 346 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -162,3 +162,5 @@ gradle-app.setting
.idea/workspace.xml
.idea/modules.xml
.idea/jarRepositories.xml

BE/src/main/resources/oauth.properties
67 changes: 67 additions & 0 deletions BE/src/main/java/com/mj_eno/sidedish/domain/user/User.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package com.mj_eno.sidedish.domain.user;

import com.mj_eno.sidedish.web.dto.EmailDTO;
import com.mj_eno.sidedish.web.dto.TokenDTO;
import com.mj_eno.sidedish.web.dto.UserInfoDTO;
import org.springframework.data.annotation.Id;

public class User {

@Id
private Long id;
private String name;
private String email;
private String userId;
private String token;

public User() {}

public User(UserInfoDTO userInfoDTO, EmailDTO emailDTO, TokenDTO tokenDTO) {
this.name = userInfoDTO.getName();
this.email = emailDTO.getEmail();
this.userId = userInfoDTO.getLogin();
this.token = tokenDTO.getAccess_token();
}

public void update(UserInfoDTO userInfoDTO, EmailDTO emailDTO, TokenDTO tokenDTO) {
this.name = userInfoDTO.getName();
this.email = emailDTO.getEmail();
this.userId = userInfoDTO.getLogin();
this.token = tokenDTO.getAccess_token();
}

public void removeToken() {
this.token = null;
}

public Long getId() {
return id;
}

public String getName() {
return name;
}

public String getEmail() {
return email;
}

public String getUserId() {
return userId;
}

public String getToken() {
return token;
}

@Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
", email='" + email + '\'' +
", userId='" + userId + '\'' +
", token='" + token + '\'' +
'}';
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.mj_eno.sidedish.domain.user;

import org.springframework.data.repository.CrudRepository;

import java.util.Optional;

public interface UserRepository extends CrudRepository<User, Long> {

Optional<User> findByEmail(String email);

Optional<User> findByToken(String token);
}
103 changes: 103 additions & 0 deletions BE/src/main/java/com/mj_eno/sidedish/service/UserService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
package com.mj_eno.sidedish.service;

import com.mj_eno.sidedish.domain.user.User;
import com.mj_eno.sidedish.domain.user.UserRepository;
import com.mj_eno.sidedish.exception.EntityNotFoundException;
import com.mj_eno.sidedish.exception.ErrorMessage;
import com.mj_eno.sidedish.web.dto.EmailDTO;
import com.mj_eno.sidedish.web.dto.TokenDTO;
import com.mj_eno.sidedish.web.dto.UserInfoDTO;
import com.mj_eno.sidedish.web.dto.UserResponseDTO;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.core.env.Environment;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriComponentsBuilder;

import java.util.List;

@PropertySource("classpath:/oauth.properties")
@Service
public class UserService {

private final UserRepository userRepository;
private final RestTemplate restTemplate;
private final Environment environment;

public UserService(UserRepository userRepository, Environment environment, RestTemplateBuilder restTemplateBuilder) {
this.userRepository = userRepository;
this.restTemplate = restTemplateBuilder.build();
this.environment = environment;
}

public UserResponseDTO login(String code) {
TokenDTO tokenDTO = tokenRequestApi(code);
UserInfoDTO userInfoDTO = userInfoRequestApi(tokenDTO.getAccess_token());
EmailDTO emailDTO = emailRequestApi(tokenDTO.getAccess_token());

if (verifyUser(emailDTO)) {
User user = findByEmail(emailDTO);
user.update(userInfoDTO, emailDTO, tokenDTO);
return new UserResponseDTO(userRepository.save(user));
}
User user = new User(userInfoDTO, emailDTO, tokenDTO);
return new UserResponseDTO(userRepository.save(user));
}

public void logout(String token) {
User user = findByToken(token);
user.removeToken();
userRepository.save(user);
}

private TokenDTO tokenRequestApi(String code) {
String id = environment.getProperty("github.client.id");
String secret = environment.getProperty("github.secret");
String url = environment.getProperty("github.access.token.url");
UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(url)
.queryParam("client_id", id)
.queryParam("client_secret", secret)
.queryParam("code", code);
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.set(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE);
httpHeaders.set(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE);
HttpEntity<?> httpEntity = new HttpEntity<>(httpHeaders);
return restTemplate.exchange(builder.toUriString(), HttpMethod.POST, httpEntity, TokenDTO.class).getBody();
}

private UserInfoDTO userInfoRequestApi(String token) {
UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl("https://api.github.com/user");
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.set(HttpHeaders.AUTHORIZATION, "token " + token);
HttpEntity<?> httpEntity = new HttpEntity<>(httpHeaders);
return restTemplate.exchange(builder.toUriString(), HttpMethod.GET, httpEntity, UserInfoDTO.class).getBody();
}

private EmailDTO emailRequestApi(String token) {
UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl("https://api.github.com/user/emails");
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.set(HttpHeaders.AUTHORIZATION, "token " + token);
HttpEntity<?> httpEntity3 = new HttpEntity<>(httpHeaders);
List<EmailDTO> emailDTOList = restTemplate.exchange(builder.toUriString(), HttpMethod.GET, httpEntity3, new ParameterizedTypeReference<List<EmailDTO>>() {}).getBody();
return emailDTOList.get(0);
}

private boolean verifyUser(EmailDTO emailDTO) {
return userRepository.findByEmail(emailDTO.getEmail()).isPresent();
}

private User findByEmail(EmailDTO emailDTO) {
return userRepository.findByEmail(emailDTO.getEmail()).orElseThrow(
() -> new EntityNotFoundException(ErrorMessage.ENTITY_NOT_FOUND)
);
}

private User findByToken(String token) {
return userRepository.findByToken(token).orElseThrow(
() -> new EntityNotFoundException(ErrorMessage.ENTITY_NOT_FOUND)
);
}
}
30 changes: 30 additions & 0 deletions BE/src/main/java/com/mj_eno/sidedish/web/UserController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package com.mj_eno.sidedish.web;

import com.mj_eno.sidedish.service.UserService;
import com.mj_eno.sidedish.web.dto.UserResponseDTO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.*;

@RestController
public class UserController {

public final UserService userService;
private final Logger logger = LoggerFactory.getLogger(DishController.class);

public UserController(UserService userService) {
this.userService = userService;
}

@PostMapping("/login")
public UserResponseDTO login(@RequestParam String code) {
logger.info("로그인 요청");
return userService.login(code);
}

@GetMapping("/logout")
public void logout(@RequestHeader String token) {
logger.info("로그아웃 요청");
userService.logout(token);
}
}
21 changes: 21 additions & 0 deletions BE/src/main/java/com/mj_eno/sidedish/web/dto/EmailDTO.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.mj_eno.sidedish.web.dto;

public class EmailDTO {

private String email;

public String getEmail() {
return email;
}

public void setEmail(String email) {
this.email = email;
}

@Override
public String toString() {
return "emailDTO{" +
"email='" + email + '\'' +
'}';
}
}
33 changes: 33 additions & 0 deletions BE/src/main/java/com/mj_eno/sidedish/web/dto/TokenDTO.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package com.mj_eno.sidedish.web.dto;

public class TokenDTO {

private String access_token;
private String token_type;
private String scope;

public void setAccess_token(String access_token) {
this.access_token = access_token;
}

public void setToken_type(String token_type) {
this.token_type = token_type;
}

public void setScope(String scope) {
this.scope = scope;
}

public String getAccess_token() {
return access_token;
}

@Override
public String toString() {
return "TokenDTO{" +
"access_token='" + access_token + '\'' +
", token_type='" + token_type + '\'' +
", scope='" + scope + '\'' +
'}';
}
}
31 changes: 31 additions & 0 deletions BE/src/main/java/com/mj_eno/sidedish/web/dto/UserInfoDTO.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package com.mj_eno.sidedish.web.dto;

public class UserInfoDTO {

private String login;
private String name;

public String getLogin() {
return login;
}

public void setLogin(String login) {
this.login = login;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

@Override
public String toString() {
return "UserInfoDTO{" +
"login='" + login + '\'' +
", name='" + name + '\'' +
'}';
}
}
34 changes: 34 additions & 0 deletions BE/src/main/java/com/mj_eno/sidedish/web/dto/UserResponseDTO.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package com.mj_eno.sidedish.web.dto;

import com.mj_eno.sidedish.domain.user.User;

public class UserResponseDTO {

private String name;
private String email;
private String userId;
private String token;

public UserResponseDTO(User user) {
this.name = user.getName();
this.email = user.getEmail();
this.userId = user.getUserId();
this.token = user.getToken();
}

public String getName() {
return name;
}

public String getEmail() {
return email;
}

public String getUserId() {
return userId;
}

public String getToken() {
return token;
}
}
13 changes: 13 additions & 0 deletions BE/src/main/resources/schema.sql
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,19 @@ SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,N
CREATE SCHEMA IF NOT EXISTS `side_dish` DEFAULT CHARACTER SET utf8;
USE `side_dish`;

-- -----------------------------------------------------
-- Table `side_dish`.`user`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `side_dish`.`user`;
CREATE TABLE IF NOT EXISTS `side_dish`.`user` (
`id` INT AUTO_INCREMENT,
`name` VARCHAR(45) NOT NULL,
`email` VARCHAR(45) NOT NULL,
`user_id` VARCHAR(45) NOT NULL,
`token` VARCHAR(255),
PRIMARY KEY (`id`))
ENGINE = InnoDB;

-- -----------------------------------------------------
-- Table `side_dish`.`best_menu_category`
-- -----------------------------------------------------
Expand Down

0 comments on commit 2266a10

Please sign in to comment.