Skip to content

Commit

Permalink
Merge pull request #90 from chhs2131/develop
Browse files Browse the repository at this point in the history
master v0.5.4
  • Loading branch information
chhs2131 authored Mar 29, 2023
2 parents a62ffa9 + d27d1c8 commit 165f54e
Show file tree
Hide file tree
Showing 55 changed files with 828 additions and 778 deletions.
19 changes: 19 additions & 0 deletions .github/workflows/codeball.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
name: Codeball
on:
pull_request: {}
pull_request_review_comment:
types: [created, edited]

jobs:
codeball_job:
runs-on: ubuntu-latest
name: Codeball
steps:
- name: Codeball
uses: sturdy-dev/codeball-action@v2
with:
# For all configuration options see https://github.com/sturdy-dev/codeball-action/blob/v2/action.yml
approvePullRequests: "true"
labelPullRequestsWhenApproved: "true"
labelPullRequestsWhenReviewNeeded: "false"
failJobsWhenReviewNeeded: "false"
3 changes: 2 additions & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ plugins {
}

group = 'com.dbsgAPI'
version = '0.4.1-SNAPSHOT'
version = '0.5.4-SNAPSHOT'
sourceCompatibility = '1.8'

configurations {
Expand All @@ -34,6 +34,7 @@ repositories {
dependencies {
//
implementation 'org.springframework.boot:spring-boot-starter-web:2.6.2'
implementation 'org.springframework.boot:spring-boot-starter-webflux'

//데이터베이스
implementation 'org.springframework.boot:spring-boot-starter-jdbc:2.6.2'
Expand Down
27 changes: 19 additions & 8 deletions readme.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,19 @@
# 공모주토피아 백엔드 서버 개발
![image](https://user-images.githubusercontent.com/10378777/223959940-c82dd679-d5fe-422f-be4f-6349c60f2f5a.png)


## 📙 프로젝트 개요
### 프로젝트 설명
- 주식 시장 신규상장(IPO) 정보를 알려주는 서비스
- 공모주 관련 플랫폼을 구축하는 것이 목표인 백엔드 프로젝트
- 크롤링된 공모주 정보를 Client에게 Restful API로 전달 및 관리
- 전자공시시스템(DART) 데이터를 직접 크롤링/가공 하여 사용
- SpringBoot, MySQL, Mybatis, OAuth2.0(카카오), REST 규격을 이용한 백엔드 담당
- 안드로이드로 서비스 중 : [PlayStore](https://play.google.com/store/apps/details?id=com.psw9999.gongmozootopia.prod.release)

**배경**
- 공모주(IPO) 관련 법이 개정되면서 일반 개인들에게도 매력적인 투자수단이 되었습니다.
- 하지만 이를 안내해주는 마땅한 서비스가 없어 해당 서비스를 개발하게되었습니다.
- 크롤링된 공모주 정보를 Client에게 Restful API로 전달 및 관리
- 공모주 관련 플랫폼을 구축하는 것이 목표인 백엔드 프로젝트

<br/>

Expand All @@ -15,10 +23,11 @@

- 담당 인원 : 1인
- Spring API
- Spring: `SpringBoot2.6.4`, `Gradle`, `IntelliJ`, `Java8`, `lombok`
- Spring: `SpringBoot2.6.4`, `Gradle`, `Java8`, `lombok`
- Security: `security`, `jjwt`
- DB: `Mybatis`, `Hikari`
- API Document: `Swagger 2.9.2`
- etc: `AOP (Transaction, LoggerAspect)`, `WebClient (HttpConnection)`
- API Document: `springdoc-openapi-ui(Swagger)`
- etc: `AOP (Transaction, LoggerAspect)`, `WebClient(webFlux)`
- Database: `MariaDB`
- ServerComputer: `Google Compute Engine`, `CentOS Linux release 8.4.2105`
- dev Tool: `HeidiSQL DataGrip`, `putty winscp`, `Postman Swagger-UI`
Expand All @@ -27,7 +36,8 @@
**공모주 데이터 크롤링**

- 담당 인원 : 3인
- 크롤러: `Python3.9`, `BS4`, `PyMysql`
- 크롤러: `Python3.7`, `BS4`, `PyMysql`
- `Linux`, `Debian`, `crontab`

<br/>

Expand All @@ -46,9 +56,10 @@
- Underwriter: 청약을 진행하는 주간사 정보와 최대 청약 개수를 확인할 수 있습니다.
- Schedule: 지정된 기간에 청약 일정이 있었는지 확인할 수 있습니다. (예. 오늘, 이번주, 지난달 등)
- Comment: 각 종목에 정보가 변화된 기록을 확인할 수 있습니다.
- AUTH: 카카오 OAuth2.0로 로그인 및 신규가입합니다.
- 추후 개인별 즐겨찾기, 보유 증권사 목록 등의 정보를 서버에서 관리하여 플랫폼간 연결성을 높일 예정입니다.
- SwaggerLink : http://server.dbsg.co.kr:8080/swagger-ui/index.html
![image](https://user-images.githubusercontent.com/10378777/199421203-2ff4fbfa-ab3e-41ad-af3f-ce7c2ab07b83.png)

![image](https://user-images.githubusercontent.com/10378777/223958261-832ce4fd-a0cb-4c4d-a88b-d1d50e4f14c7.png)

<br/>

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package com.dbsgapi.dbsgapi.api.auth.controller;

import com.dbsgapi.dbsgapi.api.auth.exception.KakaoApiException;
import com.dbsgapi.dbsgapi.api.auth.service.KakaoOauthService;
import com.dbsgapi.dbsgapi.global.authentication.AuthResponse;
import com.dbsgapi.dbsgapi.global.response.CustomException;
import io.swagger.v3.oas.annotations.Hidden;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequiredArgsConstructor
@RequestMapping("/api/v1/auth")
@Tag(name = "Auth", description = "로그인 및 계정 관리를 위한 API")
public class AuthController {
private final KakaoOauthService kakaoOauthService;

@PostMapping("/oauth/kakao")
public ResponseEntity<AuthResponse> oauthLoginKakao(@RequestParam String kakaoAccessToken) {
try {
AuthResponse result = kakaoOauthService.login(kakaoAccessToken);
System.out.println(result.toString());
return new ResponseEntity<>(result, HttpStatus.OK);
} catch (KakaoApiException e) {
throw new CustomException(e.getKakaoApiErrorCode());
}
}

@Hidden
@PostMapping("/oauth/google")
public String oauthLoginGoogle() {
return null;
}

@Hidden
@PostMapping("/#")
public String loginDbsg() {
return null;
}
}
13 changes: 13 additions & 0 deletions src/main/java/com/dbsgapi/dbsgapi/api/auth/dto/KakaoErrorDto.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.dbsgapi.dbsgapi.api.auth.dto;

import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;

@ToString
@Data
@NoArgsConstructor
public class KakaoErrorDto {
private int code;
private String msg;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package com.dbsgapi.dbsgapi.api.auth.dto;

import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;

@ToString
@Data
@NoArgsConstructor
public class KakaoProfileDto {
@JsonProperty("id")
private Long id;
@JsonProperty("connected_at")
private String connectedAt;

// @JsonProperty("kakao_account")
// private KakaoAccount kakaoAccount;
// @JsonProperty("properties")
// private Properties properties;

@Data
@NoArgsConstructor
public static class KakaoAccount {
@JsonProperty("profile")
private Profile profile;
@JsonProperty("profile_image_needs_agreement")
private boolean profileImageNeedsAgreement;
@JsonProperty("profile_nickname_needs_agreement")
private boolean profileNicknameNeedsAgreement;
}

@Data
@NoArgsConstructor
public static class Profile {
@JsonProperty("is_default_image")
private boolean isDefaultImage;
@JsonProperty("profile_image_url")
private String profileImageUrl;
@JsonProperty("thumbnail_image_url")
private String thumbnailImageUrl;
@JsonProperty("nickname")
private String nickname;
}

@Data
@NoArgsConstructor
public static class Properties {
@JsonProperty("thumbnail_image")
private String thumbnailImage;
@JsonProperty("profile_image")
private String profileImage;
@JsonProperty("nickname")
private String nickname;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.dbsgapi.dbsgapi.api.auth.dto;

import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
public class KakaoTokenInfoDto {
private long expiresInMillis;
private long id;
private long appId;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.dbsgapi.dbsgapi.api.auth.dto;

import com.dbsgapi.dbsgapi.global.authentication.OauthType;
import lombok.*;

import java.time.LocalDateTime;

@Data
@Builder
@ToString
@AllArgsConstructor
@NoArgsConstructor
public class MemberOauthAccountDto {
private String oauthId;
private OauthType oauthType;
private String memberUuid;
private LocalDateTime registDatetime;

public void setOauthType(String oauthType) {
this.oauthType = OauthType.valueOf(oauthType);
}

public int getOauthType() {
return oauthType.getId();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package com.dbsgapi.dbsgapi.api.auth.exception;

import com.dbsgapi.dbsgapi.api.auth.dto.KakaoErrorDto;
import com.dbsgapi.dbsgapi.global.response.ErrorCode;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.ToString;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;

import java.util.Arrays;

import static org.springframework.http.HttpStatus.*;

@Getter
@ToString
@AllArgsConstructor
public enum KakaoApiErrorCode implements ErrorCode {
// General
INTERNAL_ERROR(BAD_REQUEST, "-1","재시도하세요."),
PARAMETER_ERROR(BAD_REQUEST, "-2", "요청 파라미터를 확인하세요."),
OPTION_UNABLE_ERROR(FORBIDDEN, "-3", "카카오 설정 - 내 애플리케이션 - 필요한기능 활성화가 필요합니다."),
BLOCK_USER_ERROR(FORBIDDEN, "-4", "제재된 계정일 수 있습니다."),
HAVE_NOT_PERMISSION_ERROR(FORBIDDEN, "-5", "해당 API의 이해하기 문서를 참고하여 검수 진행, 권한 획득 후 재호출하세요."),
SERVICE_CHECK_ERROR(BAD_REQUEST, "-7", "서비스 점검 또는 내부 문제가 있으니 공지사항을 확인하세요."),
ILLEGAL_HEADER_ERROR(BAD_REQUEST, "-8", "올바르지 않은 헤더입니다."),
SERVICE_NOT_FOUND_ERROR(BAD_REQUEST, "-9", "서비스 종료된 API 입니다."),
API_CALL_LIMIT_ERROR(BAD_REQUEST, "-10", "API 요청 가능 횟수를 초과하였습니다."),
SERVICE_KEY_ERROR(UNAUTHORIZED, "-401", "앱키 확인 또는 토큰 갱신, 개발자 사이트에 등록된 앱 정보를 확인해주세요."),
KAKAO_USER_ERROR(BAD_REQUEST, "-501", "카카오톡 미가입 또는 유예 사용자입니다."),
IMAGE_SIZE_ERROR(BAD_REQUEST, "-602", "이미지 파일 크기가 업로드 가능한 최대 용량을 초과하였습니다."),
TIMEOUT_ERROR(BAD_REQUEST, "-603", "요청 처리 중 타임아웃이 발생하였스빈다."),
TOO_MANY_IMAGE_ERROR(BAD_REQUEST, "-606", "업로드 할 수 있는 최대 이미지 개수를 초과하였습니다."),
UNREGISTERED_KEY_ERROR(BAD_REQUEST, "-903", "등록되지않은 앱키 또는 엑세스 토큰입니다."),
IMAGE_FORMAT_ERROR(BAD_REQUEST, "-911", "지원하지 않는 이미지 파일 형식입니다."),
SYSTEM_CHECK_ERROR(SERVICE_UNAVAILABLE, "-9798", "서비스 점검중"),

// Login
LOGIN_UNREGISTERED_ERROR(BAD_REQUEST, "-101", "카카오계쩡 연결 후 재시도하세요."),
LOGIN_ALREADY_LINKED_ERROR(BAD_REQUEST, "-102", "이미 앱과 연결되어있는 사용자의 토큰입니다."),
LOGIN_DORMANT_USER_ERROR(BAD_REQUEST, "-103", "휴면 상태 또는 존재하지 않는 카카오 계정입니다."),
LOGIN_WRONG_PROPERTY_ERROR(BAD_REQUEST, "-201", "요청할 수 없는 값입니다. (내 애플리케이션 - 카카오 로그인 - 사용자 프로퍼티 확인)"),
LOGIN_NOT_AGREE_ERROR(FORBIDDEN, "-402", "사용자의 동의가 필요한 리소스입니다. (required_scopes 확인)"),
LOGIN_NO_CHILD_ERROR(UNAUTHORIZED, "-401", "14세 미만 사용자는 호츨 할 수 없게 설정되어있습니다.")
;

private final HttpStatus status;
private final String code;
private final String message;

public static KakaoApiErrorCode from(KakaoErrorDto kakaoErrorDto) {
String code = String.valueOf(kakaoErrorDto.getCode());
return from(code);
}

public static KakaoApiErrorCode from(String code) {
return Arrays.stream(KakaoApiErrorCode.values())
.filter(kakaoApiErrorCode -> kakaoApiErrorCode.getCode().equals(code))
.findAny()
.orElseThrow(() -> new IllegalStateException("지원x"));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.dbsgapi.dbsgapi.api.auth.exception;

import lombok.AllArgsConstructor;
import lombok.Getter;

@Getter
@AllArgsConstructor
public class KakaoApiException extends RuntimeException {
private final KakaoApiErrorCode kakaoApiErrorCode;
}
11 changes: 11 additions & 0 deletions src/main/java/com/dbsgapi/dbsgapi/api/auth/mapper/AuthMapper.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.dbsgapi.dbsgapi.api.auth.mapper;

import com.dbsgapi.dbsgapi.api.member.dto.MemberDto;
import com.dbsgapi.dbsgapi.api.auth.dto.MemberOauthAccountDto;
import org.apache.ibatis.annotations.Mapper;

@Mapper
public interface AuthMapper {
MemberDto getMemberByOauthAccount(MemberOauthAccountDto memberOauthAccount);
void createOauthAccount(MemberOauthAccountDto memberOauthAccount);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.dbsgapi.dbsgapi.api.auth.service;

import com.dbsgapi.dbsgapi.global.authentication.AuthResponse;

public interface KakaoOauthService {
AuthResponse login(String kakaoAccessToken);
}
Loading

0 comments on commit 165f54e

Please # to comment.