From 44011e96b11f7c40f945b401aaa49b35449586ce Mon Sep 17 00:00:00 2001 From: lkd9125 Date: Fri, 23 Feb 2024 07:21:12 +0000 Subject: [PATCH] feature/user (#8) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit User모듈 https://www.notion.so/PAV-COMMON-1a78a0b396ad46a3a3b6a49fde8e673c?pvs=4 - 회원가입추가 - 회원탈퇴 - 회원정보 조회 - 회원정보 스웨거 및 코드정리 - 암호변경 추가 - 회원정보수정 추가 - 회원정보수정 안쓰는 import삭제 - 테스트 코드추가 Co-authored-by: lkd9125 Co-committed-by: lkd9125 --- app/kac-app/build.gradle | 8 +- app/kac-app/src/docs/asciidoc/index.adoc | 69 ++++ .../app/core/security/AppSecurityConfig.java | 1 + .../src/main/resources/static/docs/index.html | 345 ++++++++++++++++-- .../test/java/kr/co/palnet/kac/BaseTest.java | 78 +++- .../account/UserAccountControllerTest.java | 228 ++++++++++++ .../kr/co/palnet/kac/util/EncryptUtil.java | 13 + .../kac/data/pty/model/PtyCstmrDtl.java | 3 +- .../kac/data/pty/model/PtyCstmrGroup.java | 6 +- .../kac/data/pty/model/PtyTermsAgreeTxn.java | 5 +- .../pty/repository/PtyCstmrBasRepository.java | 2 +- .../pty/repository/PtyCstmrDtlRepository.java | 2 +- .../repository/PtyCstmrGroupRepository.java | 12 + .../pty/repository/PtyGroupBasRepository.java | 2 + .../pty/service/PtyCstmrDomainService.java | 27 ++ .../pty/service/PtyGroupDomainService.java | 53 +++ .../pty/service/PtyTermsDomainService.java | 19 + web/api-user/build.gradle | 2 + .../controller/UserAccountController.java | 74 ++++ .../v1/user/account/model/PtyCstmrDTO.java | 84 +++++ .../v1/user/account/model/PtyCstmrDtlDTO.java | 63 ++++ .../account/model/detail/SearchUserRS.java | 40 ++ .../model/register/AgreeTermsModel.java | 14 + .../model/register/FormRegisterRQ.java | 111 ++++++ .../model/update/UpdatePasswordRQ.java | 19 + .../account/model/update/UpdateUserRQ.java | 15 + .../account/service/UserAccountService.java | 249 +++++++++++++ .../controller/UserCertificateController.java | 17 + .../java/kr/co/palnet/kac/util/HttpUtils.java | 35 ++ .../kac/config/security/SecurityConfig.java | 5 +- 30 files changed, 1549 insertions(+), 52 deletions(-) create mode 100644 app/kac-app/src/test/java/kr/co/palnet/kac/user/account/UserAccountControllerTest.java create mode 100644 data/pty/src/main/java/kr/co/palnet/kac/data/pty/service/PtyGroupDomainService.java create mode 100644 data/pty/src/main/java/kr/co/palnet/kac/data/pty/service/PtyTermsDomainService.java create mode 100644 web/api-user/src/main/java/kr/co/palnet/kac/api/v1/user/account/controller/UserAccountController.java create mode 100644 web/api-user/src/main/java/kr/co/palnet/kac/api/v1/user/account/model/PtyCstmrDTO.java create mode 100644 web/api-user/src/main/java/kr/co/palnet/kac/api/v1/user/account/model/PtyCstmrDtlDTO.java create mode 100644 web/api-user/src/main/java/kr/co/palnet/kac/api/v1/user/account/model/detail/SearchUserRS.java create mode 100644 web/api-user/src/main/java/kr/co/palnet/kac/api/v1/user/account/model/register/AgreeTermsModel.java create mode 100644 web/api-user/src/main/java/kr/co/palnet/kac/api/v1/user/account/model/register/FormRegisterRQ.java create mode 100644 web/api-user/src/main/java/kr/co/palnet/kac/api/v1/user/account/model/update/UpdatePasswordRQ.java create mode 100644 web/api-user/src/main/java/kr/co/palnet/kac/api/v1/user/account/model/update/UpdateUserRQ.java create mode 100644 web/api-user/src/main/java/kr/co/palnet/kac/api/v1/user/account/service/UserAccountService.java create mode 100644 web/api-user/src/main/java/kr/co/palnet/kac/api/v1/user/certificate/controller/UserCertificateController.java create mode 100644 web/api-user/src/main/java/kr/co/palnet/kac/util/HttpUtils.java diff --git a/app/kac-app/build.gradle b/app/kac-app/build.gradle index 215278e..59af035 100644 --- a/app/kac-app/build.gradle +++ b/app/kac-app/build.gradle @@ -39,13 +39,7 @@ dependencies { implementation project(":common:util") implementation project(":web:security") implementation project(":web:api-common") - -// implementation project(":data:cns") -// implementation project(":data:com") -// implementation project(":data:ctr") -// implementation project(":data:flt") -// implementation project(":data:other") -// implementation project(":data:pty") + implementation project(":web:api-user") } ext { diff --git a/app/kac-app/src/docs/asciidoc/index.adoc b/app/kac-app/src/docs/asciidoc/index.adoc index 1751cce..fee2ef1 100644 --- a/app/kac-app/src/docs/asciidoc/index.adoc +++ b/app/kac-app/src/docs/asciidoc/index.adoc @@ -172,4 +172,73 @@ include::{snippets}/com/code/lang/delete/query-parameters.adoc[] ==== [HTTP RESPONSE INFO] include::{snippets}/com/code/lang/delete/http-response.adoc[] +*** + +[[User-Account-API]] +== User-Account API + +=== [User 회원가입] + +==== [HTTP REQUEST INFO] +include::{snippets}/user/account/register/http-request.adoc[] + +include::{snippets}/user/account/register/request-fields.adoc[] + +==== [HTTP RESPONSE INFO] +include::{snippets}/user/account/register/http-response.adoc[] + +*** + +=== [User 회원탈퇴] + +==== [HTTP REQUEST INFO] +include::{snippets}/user/account/delete/http-request.adoc[] + +include::{snippets}/user/account/delete/request-headers.adoc[] + +==== [HTTP RESPONSE INFO] +include::{snippets}/user/account/delete/http-response.adoc[] + +*** + +=== [User 회원정보 조회] + +==== [HTTP REQUEST INFO] +include::{snippets}/user/account/profile/http-request.adoc[] + +include::{snippets}/user/account/profile/request-headers.adoc[] + +==== [HTTP RESPONSE INFO] +include::{snippets}/user/account/profile/http-response.adoc[] + +include::{snippets}/user/account/profile/response-fields.adoc[] + +*** + +=== [User 회원암호 변경] + +==== [HTTP REQUEST INFO] +include::{snippets}/user/account/update/pswd/http-request.adoc[] + +include::{snippets}/user/account/update/pswd/request-headers.adoc[] + +include::{snippets}/user/account/update/pswd/request-fields.adoc[] + +==== [HTTP RESPONSE INFO] +include::{snippets}/user/account/update/pswd/http-response.adoc[] + +*** + +=== [User 회원정보 변경] + +==== [HTTP REQUEST INFO] +include::{snippets}/user/account/update/http-request.adoc[] + +include::{snippets}/user/account/update/request-headers.adoc[] + +include::{snippets}/user/account/update/request-fields.adoc[] + +==== [HTTP RESPONSE INFO] +include::{snippets}/user/account/update/http-response.adoc[] + *** \ No newline at end of file diff --git a/app/kac-app/src/main/java/kr/co/palnet/kac/app/core/security/AppSecurityConfig.java b/app/kac-app/src/main/java/kr/co/palnet/kac/app/core/security/AppSecurityConfig.java index 48e8893..1e508c4 100644 --- a/app/kac-app/src/main/java/kr/co/palnet/kac/app/core/security/AppSecurityConfig.java +++ b/app/kac-app/src/main/java/kr/co/palnet/kac/app/core/security/AppSecurityConfig.java @@ -27,6 +27,7 @@ public class AppSecurityConfig extends SecurityConfig { // 시큐리티 적용 안하는 URL 목록 private final String[] IGNORE_URL = { "/v1/com/code/**", + "/v1/user/account/register", }; // 권한(ROLE)별 URL diff --git a/app/kac-app/src/main/resources/static/docs/index.html b/app/kac-app/src/main/resources/static/docs/index.html index ddab2f6..2fdafe0 100644 --- a/app/kac-app/src/main/resources/static/docs/index.html +++ b/app/kac-app/src/main/resources/static/docs/index.html @@ -464,6 +464,11 @@ body.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-b
  • [Code 언어 삭제]
  • +
  • User-Account API + +
  • @@ -515,11 +520,20 @@ Host: localhost:8080
    HTTP/1.1 200 OK
    +Vary: Origin
    +Vary: Access-Control-Request-Method
    +Vary: Access-Control-Request-Headers
     Content-Type: application/json;charset=UTF-8
    +X-Content-Type-Options: nosniff
    +X-XSS-Protection: 0
    +Cache-Control: no-cache, no-store, max-age=0, must-revalidate
    +Pragma: no-cache
    +Expires: 0
    +X-Frame-Options: DENY
     Content-Length: 143
     
     [ {
    -  "groupCd" : "NEW_GROUP_1707924397",
    +  "groupCd" : "NEW_GROUP_1708411842",
       "siteCd" : "KAC",
       "groupCdNm" : "신규그룹001",
       "rm" : "비고....",
    @@ -626,7 +640,7 @@ Content-Length: 143
     

    [HTTP REQUEST INFO]

    -
    GET /v1/com/code/code?groupCd=NEW_GROUP_1707924397&langDivCd=ko_KR HTTP/1.1
    +
    GET /v1/com/code/code?groupCd=NEW_GROUP_1708411842&langDivCd=ko_KR HTTP/1.1
     Content-Type: application/json;charset=UTF-8
     Accept: application/json
     Host: localhost:8080
    @@ -664,11 +678,20 @@ Host: localhost:8080
    HTTP/1.1 200 OK
    +Vary: Origin
    +Vary: Access-Control-Request-Method
    +Vary: Access-Control-Request-Headers
     Content-Type: application/json;charset=UTF-8
    +X-Content-Type-Options: nosniff
    +X-XSS-Protection: 0
    +Cache-Control: no-cache, no-store, max-age=0, must-revalidate
    +Pragma: no-cache
    +Expires: 0
    +X-Frame-Options: DENY
     Content-Length: 190
     
     [ {
    -  "groupCd" : "NEW_GROUP_1707924397",
    +  "groupCd" : "NEW_GROUP_1708411842",
       "cdId" : "NEW_CODE001",
       "cdNm" : "신규코드001",
       "upperCd" : null,
    @@ -759,11 +782,20 @@ Host: localhost:8080
    HTTP/1.1 200 OK
    +Vary: Origin
    +Vary: Access-Control-Request-Method
    +Vary: Access-Control-Request-Headers
     Content-Type: application/json;charset=UTF-8
    +X-Content-Type-Options: nosniff
    +X-XSS-Protection: 0
    +Cache-Control: no-cache, no-store, max-age=0, must-revalidate
    +Pragma: no-cache
    +Expires: 0
    +X-Frame-Options: DENY
     Content-Length: 143
     
     [ {
    -  "groupCd" : "NEW_GROUP_1707924397",
    +  "groupCd" : "NEW_GROUP_1708411843",
       "siteCd" : "KAC",
       "groupCdNm" : "신규그룹001",
       "rm" : "비고....",
    @@ -835,7 +867,7 @@ Content-Length: 118
     Host: localhost:8080
     
     {
    -  "groupCd" : "NEW_GROUP_1707924397",
    +  "groupCd" : "NEW_GROUP_1708411843",
       "siteCd" : "KAC",
       "groupCdNm" : "신규그룹001",
       "rm" : "비고...."
    @@ -890,18 +922,27 @@ Host: localhost:8080
     
    HTTP/1.1 200 OK
    +Vary: Origin
    +Vary: Access-Control-Request-Method
    +Vary: Access-Control-Request-Headers
     Content-Type: application/json;charset=UTF-8
    -Content-Length: 276
    +X-Content-Type-Options: nosniff
    +X-XSS-Protection: 0
    +Cache-Control: no-cache, no-store, max-age=0, must-revalidate
    +Pragma: no-cache
    +Expires: 0
    +X-Frame-Options: DENY
    +Content-Length: 275
     
     {
    -  "groupCd" : "NEW_GROUP_1707924397",
    +  "groupCd" : "NEW_GROUP_1708411843",
       "siteCd" : "KAC",
       "groupCdNm" : "신규그룹001",
       "rm" : "비고....",
       "createUserId" : "CREATE_USER",
    -  "createDt" : "2024-02-15T00:26:37.902778",
    +  "createDt" : "2024-02-20T15:50:43.127816",
       "updateUserId" : "CREATE_USER",
    -  "updateDt" : "2024-02-15T00:26:37.902782"
    +  "updateDt" : "2024-02-20T15:50:43.12782"
     }
    @@ -987,7 +1028,7 @@ Content-Length: 132 Host: localhost:8080 { - "groupCd" : "NEW_GROUP_1707924397", + "groupCd" : "NEW_GROUP_1708411843", "cdId" : "NEW_CODE001", "sortOrdr" : 0, "addInfoValue" : "추가!!", @@ -1049,20 +1090,29 @@ Host: localhost:8080
    HTTP/1.1 200 OK
    +Vary: Origin
    +Vary: Access-Control-Request-Method
    +Vary: Access-Control-Request-Headers
     Content-Type: application/json;charset=UTF-8
    +X-Content-Type-Options: nosniff
    +X-XSS-Protection: 0
    +Cache-Control: no-cache, no-store, max-age=0, must-revalidate
    +Pragma: no-cache
    +Expires: 0
    +X-Frame-Options: DENY
     Content-Length: 310
     
     {
    -  "groupCd" : "NEW_GROUP_1707924397",
    +  "groupCd" : "NEW_GROUP_1708411843",
       "cdId" : "NEW_CODE001",
       "upperCd" : null,
       "sortOrdr" : 0,
       "addInfoValue" : "추가!!",
       "useYn" : "Y",
       "createUserId" : "CREATE_USER",
    -  "createDt" : "2024-02-15T00:26:37.887931",
    +  "createDt" : "2024-02-20T15:50:43.107273",
       "updateUserId" : "CREATE_USER",
    -  "updateDt" : "2024-02-15T00:26:37.887936"
    +  "updateDt" : "2024-02-20T15:50:43.107277"
     }
    @@ -1160,7 +1210,7 @@ Content-Length: 144 Host: localhost:8080 { - "groupCd" : "NEW_GROUP_1707924397", + "groupCd" : "NEW_GROUP_1708411842", "cdId" : "NEW_CODE001", "langDivCd" : "ko_KR", "cdNm" : "신규코드001", @@ -1222,19 +1272,28 @@ Host: localhost:8080
    HTTP/1.1 200 OK
    +Vary: Origin
    +Vary: Access-Control-Request-Method
    +Vary: Access-Control-Request-Headers
     Content-Type: application/json;charset=UTF-8
    +X-Content-Type-Options: nosniff
    +X-XSS-Protection: 0
    +Cache-Control: no-cache, no-store, max-age=0, must-revalidate
    +Pragma: no-cache
    +Expires: 0
    +X-Frame-Options: DENY
     Content-Length: 302
     
     {
    -  "groupCd" : "NEW_GROUP_1707924397",
    +  "groupCd" : "NEW_GROUP_1708411842",
       "cdId" : "NEW_CODE001",
       "langDivCd" : "ko_KR",
       "cdNm" : "신규코드001",
       "rm" : "비고....",
       "createUserId" : "CREATE_USER",
    -  "createDt" : "2024-02-15T00:26:37.826757",
    +  "createDt" : "2024-02-20T15:50:43.009038",
       "updateUserId" : "CREATE_USER",
    -  "updateDt" : "2024-02-15T00:26:37.826761"
    +  "updateDt" : "2024-02-20T15:50:43.009043"
     }
    @@ -1326,7 +1385,7 @@ Content-Length: 118 Host: localhost:8080 { - "groupCd" : "NEW_GROUP_1707924397", + "groupCd" : "NEW_GROUP_1708411843", "siteCd" : "KAC", "groupCdNm" : "신규그룹001", "rm" : "비고...." @@ -1381,18 +1440,27 @@ Host: localhost:8080
    HTTP/1.1 200 OK
    +Vary: Origin
    +Vary: Access-Control-Request-Method
    +Vary: Access-Control-Request-Headers
     Content-Type: application/json;charset=UTF-8
    -Content-Length: 275
    +X-Content-Type-Options: nosniff
    +X-XSS-Protection: 0
    +Cache-Control: no-cache, no-store, max-age=0, must-revalidate
    +Pragma: no-cache
    +Expires: 0
    +X-Frame-Options: DENY
    +Content-Length: 276
     
     {
    -  "groupCd" : "NEW_GROUP_1707924397",
    +  "groupCd" : "NEW_GROUP_1708411843",
       "siteCd" : "KAC",
       "groupCdNm" : "신규그룹001",
       "rm" : "비고....",
       "createUserId" : "CREATE_USER",
    -  "createDt" : "2024-02-15T00:26:37.84228",
    +  "createDt" : "2024-02-20T15:50:43.031642",
       "updateUserId" : "UPDATE_USER",
    -  "updateDt" : "2024-02-15T00:26:37.844978"
    +  "updateDt" : "2024-02-20T15:50:43.035007"
     }
    @@ -1478,7 +1546,7 @@ Content-Length: 132 Host: localhost:8080 { - "groupCd" : "NEW_GROUP_1707924397", + "groupCd" : "NEW_GROUP_1708411842", "cdId" : "NEW_CODE001", "sortOrdr" : 0, "addInfoValue" : "수정!!", @@ -1540,20 +1608,29 @@ Host: localhost:8080
    HTTP/1.1 200 OK
    +Vary: Origin
    +Vary: Access-Control-Request-Method
    +Vary: Access-Control-Request-Headers
     Content-Type: application/json;charset=UTF-8
    +X-Content-Type-Options: nosniff
    +X-XSS-Protection: 0
    +Cache-Control: no-cache, no-store, max-age=0, must-revalidate
    +Pragma: no-cache
    +Expires: 0
    +X-Frame-Options: DENY
     Content-Length: 310
     
     {
    -  "groupCd" : "NEW_GROUP_1707924397",
    +  "groupCd" : "NEW_GROUP_1708411842",
       "cdId" : "NEW_CODE001",
       "upperCd" : null,
       "sortOrdr" : 0,
       "addInfoValue" : "수정!!",
       "useYn" : "Y",
       "createUserId" : "CREATE_USER",
    -  "createDt" : "2024-02-15T00:26:37.757743",
    +  "createDt" : "2024-02-20T15:50:42.915944",
       "updateUserId" : "UPDATE_USER",
    -  "updateDt" : "2024-02-15T00:26:37.770459"
    +  "updateDt" : "2024-02-20T15:50:42.938404"
     }
    @@ -1651,7 +1728,7 @@ Content-Length: 143 Host: localhost:8080 { - "groupCd" : "NEW_GROUP_1707924397", + "groupCd" : "NEW_GROUP_1708411842", "cdId" : "NEW_CODE001", "langDivCd" : "ko_KR", "cdNm" : "신규코드001", @@ -1713,19 +1790,28 @@ Host: localhost:8080
    HTTP/1.1 200 OK
    +Vary: Origin
    +Vary: Access-Control-Request-Method
    +Vary: Access-Control-Request-Headers
     Content-Type: application/json;charset=UTF-8
    +X-Content-Type-Options: nosniff
    +X-XSS-Protection: 0
    +Cache-Control: no-cache, no-store, max-age=0, must-revalidate
    +Pragma: no-cache
    +Expires: 0
    +X-Frame-Options: DENY
     Content-Length: 301
     
     {
    -  "groupCd" : "NEW_GROUP_1707924397",
    +  "groupCd" : "NEW_GROUP_1708411842",
       "cdId" : "NEW_CODE001",
       "langDivCd" : "ko_KR",
       "cdNm" : "신규코드001",
       "rm" : "수정...",
       "createUserId" : "CREATE_USER",
    -  "createDt" : "2024-02-15T00:26:37.798977",
    +  "createDt" : "2024-02-20T15:50:42.973527",
       "updateUserId" : "UPDATE_USER",
    -  "updateDt" : "2024-02-15T00:26:37.803818"
    +  "updateDt" : "2024-02-20T15:50:42.978852"
     }
    @@ -1842,7 +1928,16 @@ Host: localhost:8080

    [HTTP RESPONSE INFO]

    -
    HTTP/1.1 200 OK
    +
    HTTP/1.1 200 OK
    +Vary: Origin
    +Vary: Access-Control-Request-Method
    +Vary: Access-Control-Request-Headers
    +X-Content-Type-Options: nosniff
    +X-XSS-Protection: 0
    +Cache-Control: no-cache, no-store, max-age=0, must-revalidate
    +Pragma: no-cache
    +Expires: 0
    +X-Frame-Options: DENY

    @@ -1891,7 +1986,16 @@ Host: localhost:8080

    [HTTP RESPONSE INFO]

    -
    HTTP/1.1 200 OK
    +
    HTTP/1.1 200 OK
    +Vary: Origin
    +Vary: Access-Control-Request-Method
    +Vary: Access-Control-Request-Headers
    +X-Content-Type-Options: nosniff
    +X-XSS-Protection: 0
    +Cache-Control: no-cache, no-store, max-age=0, must-revalidate
    +Pragma: no-cache
    +Expires: 0
    +X-Frame-Options: DENY

    @@ -1945,8 +2049,181 @@ Host: localhost:8080

    [HTTP RESPONSE INFO]

    -
    HTTP/1.1 200 OK
    +
    HTTP/1.1 200 OK
    +Vary: Origin
    +Vary: Access-Control-Request-Method
    +Vary: Access-Control-Request-Headers
    +X-Content-Type-Options: nosniff
    +X-XSS-Protection: 0
    +Cache-Control: no-cache, no-store, max-age=0, must-revalidate
    +Pragma: no-cache
    +Expires: 0
    +X-Frame-Options: DENY
    +
    +
    +
    +
    +
    + + +
    +

    User-Account API

    +
    +
    +

    [User 회원가입]

    +
    +

    [HTTP REQUEST INFO]

    +
    +
    +
    POST /v1/user/account/register HTTP/1.1
    +Content-Type: application/json;charset=UTF-8
    +Accept: application/json
    +Content-Length: 337
    +Host: localhost:8080
    +
    +{
    +  "cstrmDivCd" : "MEMBER",
    +  "cstrmStatusCd" : "ACTIVE",
    +  "userId" : "TEST_1708411843171",
    +  "authId" : "USER",
    +  "siteCode" : "DRONE",
    +  "userPswd" : "palnet!234",
    +  "joinCrtfyCd" : "HP_CRTFD",
    +  "memberName" : "이경도",
    +  "brthdyDate" : "1999-09-07",
    +  "email" : "lkd9125@naver.com",
    +  "hpno" : "01083703435",
    +  "clncd" : "+82"
    +}
    +
    +
    + ++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    파라미터타입설명필수

    cstrmDivCd

    String

    회원타입 코드

    true

    cstrmStatusCd

    String

    회원 활성화 코드

    true

    userId

    String

    아이디

    true

    authId

    String

    권한 값

    true

    siteCode

    String

    사이트 코드

    true

    userPswd

    String

    암호

    true

    joinCrtfyCd

    String

    가입인증 분류 코드

    true

    memberName

    String

    이름

    true

    brthdyDate

    String

    생년월일

    true

    email

    String

    이메일

    true

    hpno

    String

    휴대폰 번호

    true

    clncd

    String

    휴대폰 국가번호

    true

    terms

    Array

    동의 약관 리스트

    false

    terms[].termsSno

    Number

    약관 식별번호

    true

    terms[].agreeYn

    String

    약관 동의여부

    true

    +
    +
    +

    [HTTP RESPONSE INFO]

    +
    +
    +
    HTTP/1.1 201 Created
    +Vary: Origin
    +Vary: Access-Control-Request-Method
    +Vary: Access-Control-Request-Headers
    +X-Content-Type-Options: nosniff
    +X-XSS-Protection: 0
    +Cache-Control: no-cache, no-store, max-age=0, must-revalidate
    +Pragma: no-cache
    +Expires: 0
    +X-Frame-Options: DENY
    +
    +
    +

    Unresolved directive in index.adoc - include::./build/generated-snippets/user/account/register/response-fields.adoc[]


    @@ -1957,7 +2234,7 @@ Host: localhost:8080 diff --git a/app/kac-app/src/test/java/kr/co/palnet/kac/BaseTest.java b/app/kac-app/src/test/java/kr/co/palnet/kac/BaseTest.java index 054591a..b96ab51 100644 --- a/app/kac-app/src/test/java/kr/co/palnet/kac/BaseTest.java +++ b/app/kac-app/src/test/java/kr/co/palnet/kac/BaseTest.java @@ -1,18 +1,33 @@ package kr.co.palnet.kac; import com.fasterxml.jackson.databind.ObjectMapper; +import jakarta.servlet.ServletException; +import kr.co.palnet.kac.api.v1.user.account.model.detail.SearchUserRS; +import kr.co.palnet.kac.api.v1.user.account.model.register.FormRegisterRQ; +import kr.co.palnet.kac.api.v1.user.account.service.UserAccountService; import kr.co.palnet.kac.app.KacAppApplication; +import kr.co.palnet.kac.config.security.model.BaseUserDetails; +import kr.co.palnet.kac.config.security.service.BaseUserDetailsService; +import kr.co.palnet.kac.config.security.util.JwtUtil; +import kr.co.palnet.kac.util.ObjectMapperUtils; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.mock.web.MockFilterConfig; import org.springframework.restdocs.RestDocumentationContextProvider; import org.springframework.restdocs.RestDocumentationExtension; import org.springframework.restdocs.mockmvc.MockMvcRestDocumentation; +import org.springframework.security.config.BeanIds; +import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.setup.MockMvcBuilders; import org.springframework.web.context.WebApplicationContext; import org.springframework.web.filter.CharacterEncodingFilter; +import org.springframework.web.filter.DelegatingFilterProxy; + +import java.time.LocalDate; +import java.time.LocalDateTime; import static org.springframework.restdocs.operation.preprocess.Preprocessors.modifyUris; import static org.springframework.restdocs.operation.preprocess.Preprocessors.prettyPrint; @@ -24,12 +39,24 @@ public class BaseTest { @Autowired protected WebApplicationContext webApplicationContext; + @Autowired + protected UserAccountService userAccountService; + + @Autowired + protected BaseUserDetailsService baseUserDetailsService; + public MockMvc mockMvc; + protected final String CREATE_PASSWORD = "palnet!234"; + @BeforeEach - public void setUpAll(RestDocumentationContextProvider restDocumentationContextProvider){ + public void setUpAll(RestDocumentationContextProvider restDocumentationContextProvider) throws ServletException { + DelegatingFilterProxy delegateProxyFilter = new DelegatingFilterProxy(); + delegateProxyFilter.init(new MockFilterConfig(webApplicationContext.getServletContext(), BeanIds.SPRING_SECURITY_FILTER_CHAIN)); + + this.mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext) // @Autowired로 빈주입 받은 context - .addFilter(new CharacterEncodingFilter("UTF-8", true)) // UTF-8 인코딩 필터 + .addFilters(new CharacterEncodingFilter("UTF-8", true), delegateProxyFilter) // UTF-8 인코딩 필터, SecurityFilter .apply( MockMvcRestDocumentation.documentationConfiguration(restDocumentationContextProvider) .operationPreprocessors() @@ -42,4 +69,51 @@ public class BaseTest { ) .build(); } + + protected String getUserToken(){ + + String username = "TEST_" + System.currentTimeMillis(); + + String jsonRQ = """ + { + "cstrmDivCd" : "MEMBER", + "cstrmStatusCd" : "ACTIVE", + "userId" : "%s", + "authId" : "USER", + "siteCode" : "DRONE", + "userPswd" : "%s", + "joinCrtfyCd" : "HP_CRTFD", + "memberName" : "이경도", + "brthdyDate" : "1999-09-07", + "email" : "lkd9125@naver.com", + "hpno" : "01083703435", + "clncd" : "+82" + } + """.formatted(username, this.CREATE_PASSWORD); + + FormRegisterRQ rq = new FormRegisterRQ(); + rq.setCstrmDivCd("MEMBER"); + rq.setCstrmStatusCd("ACTIVE"); + rq.setUserId(username); + rq.setAuthId("USER"); + rq.setSiteCode("DRONE"); + rq.setUserPswd("palnet!234"); + rq.setJoinCrtfyCd("HP_CRTFD"); + rq.setMemberName("이경도"); + rq.setBrthdyDate(LocalDate.of(1999, 9, 7)); + rq.setEmail("lkd9125@naver.com"); + rq.setHpno("01083703435"); + rq.setClncd("+82"); + + try{ + userAccountService.createUser(rq); + } catch (Exception e){ + e.printStackTrace(); + } + + BaseUserDetails userDetails = (BaseUserDetails) baseUserDetailsService.loadUserByUsername(username); + + return JwtUtil.makeAuthToken(userDetails); + } + } diff --git a/app/kac-app/src/test/java/kr/co/palnet/kac/user/account/UserAccountControllerTest.java b/app/kac-app/src/test/java/kr/co/palnet/kac/user/account/UserAccountControllerTest.java new file mode 100644 index 0000000..e5f72f1 --- /dev/null +++ b/app/kac-app/src/test/java/kr/co/palnet/kac/user/account/UserAccountControllerTest.java @@ -0,0 +1,228 @@ +package kr.co.palnet.kac.user.account; + + +import kr.co.palnet.kac.BaseTest; +import kr.co.palnet.kac.api.v1.user.account.service.UserAccountService; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.MediaType; +import org.springframework.restdocs.headers.HeaderDocumentation; +import org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders; +import org.springframework.restdocs.payload.JsonFieldType; +import org.springframework.transaction.annotation.Transactional; + +import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document; +import static org.springframework.restdocs.operation.preprocess.Preprocessors.preprocessResponse; +import static org.springframework.restdocs.operation.preprocess.Preprocessors.prettyPrint; +import static org.springframework.restdocs.payload.PayloadDocumentation.*; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +public class UserAccountControllerTest extends BaseTest { + + @Autowired + private UserAccountService userAccountService; + + private final String BASE_URL = "/v1/user/account"; + + private final String GRANT_TYPE = "Bearer"; + + @DisplayName("회원정보 변경") + @Test + @Transactional + public void updateUser() throws Exception{ + String jsonRQ = """ + { + "email" : "lkd9125@naver.com", + "hpno" : "01083703435" + } + """; + + String token = this.getUserToken(); + + this.mockMvc.perform( + put(this.BASE_URL + "/update") + .contentType(MediaType.APPLICATION_JSON_VALUE) + .content(jsonRQ) + .accept(MediaType.APPLICATION_JSON_VALUE) + .header("Authorization", GRANT_TYPE + " " + token) + ) + .andDo(print()) + .andDo( + document( + "user/account/update", + preprocessResponse(prettyPrint()), + HeaderDocumentation.requestHeaders( + HeaderDocumentation.headerWithName("Authorization").description("Access토큰 [로그인 발급]") + ), + requestFields( + fieldWithPath("email").type(JsonFieldType.STRING).description("바꿀 이메일").optional(), + fieldWithPath("hpno").type(JsonFieldType.STRING).description("바꿀 전화번호").optional() + ) + ) + ) + .andExpect(status().isOk()); + } + + @DisplayName("암호 변경") + @Test + @Transactional + public void updatePassword() throws Exception{ + + String jsonRQ = """ + { + "userPswd" : "%s", + "newPswd" : "palnet!234", + "newPswdConfirm" : "palnet!234" + } + """.formatted(this.CREATE_PASSWORD); + + String token = this.getUserToken(); + + this.mockMvc.perform( + put(this.BASE_URL + "/update/pswd") + .contentType(MediaType.APPLICATION_JSON_VALUE) + .content(jsonRQ) + .accept(MediaType.APPLICATION_JSON_VALUE) + .header("Authorization", GRANT_TYPE + " " + token) + ) + .andDo(print()) + .andDo( + document( + "user/account/update/pswd", + preprocessResponse(prettyPrint()), + HeaderDocumentation.requestHeaders( + HeaderDocumentation.headerWithName("Authorization").description("Access토큰 [로그인 발급]") + ), + requestFields( + fieldWithPath("userPswd").type(JsonFieldType.STRING).description("현재 암호").optional(), + fieldWithPath("newPswd").type(JsonFieldType.STRING).description("바뀔 암호"), + fieldWithPath("newPswdConfirm").type(JsonFieldType.STRING).description("바뀔 암호 확인") + ) + ) + ) + .andExpect(status().isOk()); + } + + @DisplayName("회원정보 조회") + @Test + @Transactional + public void getUserInfo() throws Exception{ + String token = this.getUserToken(); + + this.mockMvc.perform( + get(this.BASE_URL + "/profile") + .contentType(MediaType.APPLICATION_JSON_VALUE) + .accept(MediaType.APPLICATION_JSON_VALUE) + .header("Authorization", GRANT_TYPE + " " + token) + ) + .andDo(print()) + .andDo( + document( + "user/account/profile", // gradle build를 하게 되면 generated-snippets에 만들어질 폴더이름 + preprocessResponse(prettyPrint()), + HeaderDocumentation.requestHeaders( + HeaderDocumentation.headerWithName("Authorization").description("Access토큰 [로그인 발급]") + ), + responseFields( + fieldWithPath("memberName").type(JsonFieldType.STRING).description("회원 이름"), + fieldWithPath("brthdyDate").type(JsonFieldType.STRING).description("생년월일"), + fieldWithPath("cntryCd").type(JsonFieldType.STRING).description("국적 구분코드"), + fieldWithPath("email").type(JsonFieldType.STRING).description("이메일"), + fieldWithPath("hpno").type(JsonFieldType.STRING).description("휴대폰 번호"), + fieldWithPath("userId").type(JsonFieldType.STRING).description("아이디"), + fieldWithPath("updateDt").type(JsonFieldType.STRING).description("수정일시"), + fieldWithPath("updateuserId").type(JsonFieldType.STRING).description("수정자 아이디"), + fieldWithPath("cptAuthCode").type(JsonFieldType.STRING).description("각 항청 구분코드") + ) + ) + ) + .andExpect(status().isOk()); + } + + @DisplayName("회원탈퇴") + @Test + @Transactional + public void deleteUser() throws Exception{ + String token = this.getUserToken(); + + this.mockMvc.perform( + RestDocumentationRequestBuilders.delete(this.BASE_URL + "/delete") + .contentType(MediaType.APPLICATION_JSON_VALUE) + .accept(MediaType.APPLICATION_JSON_VALUE) + .header("Authorization", GRANT_TYPE + " " + token) + ) + .andDo(print()) + .andDo( + document( + "user/account/delete", // gradle build를 하게 되면 generated-snippets에 만들어질 폴더이름 + preprocessResponse(prettyPrint()), + HeaderDocumentation.requestHeaders( + HeaderDocumentation.headerWithName("Authorization").description("Access토큰 [로그인 발급]") + ) + ) + ) + .andExpect(status().isOk()); + } + + @DisplayName("회원가입") + @Test + @Transactional + public void register() throws Exception{ + + String username = "TEST_" + System.currentTimeMillis(); + + String jsonRQ = """ + { + "cstrmDivCd" : "MEMBER", + "cstrmStatusCd" : "ACTIVE", + "userId" : "%s", + "authId" : "USER", + "siteCode" : "DRONE", + "userPswd" : "palnet!234", + "joinCrtfyCd" : "HP_CRTFD", + "memberName" : "이경도", + "brthdyDate" : "1999-09-07", + "email" : "lkd9125@naver.com", + "hpno" : "01083703435", + "clncd" : "+82" + } + """.formatted(username); + + this.mockMvc.perform( + post(this.BASE_URL + "/register") + .contentType(MediaType.APPLICATION_JSON_VALUE) + .content(jsonRQ) + .accept(MediaType.APPLICATION_JSON_VALUE) + ) + .andDo(print()) + .andDo( + document( + "user/account/register", // gradle build를 하게 되면 generated-snippets에 만들어질 폴더이름 + preprocessResponse(prettyPrint()), + requestFields( + fieldWithPath("cstrmDivCd").type(JsonFieldType.STRING).description("회원타입 코드"), + fieldWithPath("cstrmStatusCd").type(JsonFieldType.STRING).description("회원 활성화 코드"), + fieldWithPath("userId").type(JsonFieldType.STRING).description("아이디"), + fieldWithPath("authId").type(JsonFieldType.STRING).description("권한 값"), + fieldWithPath("siteCode").type(JsonFieldType.STRING).description("사이트 코드"), + fieldWithPath("userPswd").type(JsonFieldType.STRING).description("암호"), + fieldWithPath("joinCrtfyCd").type(JsonFieldType.STRING).description("가입인증 분류 코드"), + fieldWithPath("memberName").type(JsonFieldType.STRING).description("이름"), + fieldWithPath("brthdyDate").type(JsonFieldType.STRING).description("생년월일"), + fieldWithPath("email").type(JsonFieldType.STRING).description("이메일"), + fieldWithPath("hpno").type(JsonFieldType.STRING).description("휴대폰 번호"), + fieldWithPath("clncd").type(JsonFieldType.STRING).description("휴대폰 국가번호"), + fieldWithPath("terms").type(JsonFieldType.ARRAY).description("동의 약관 리스트").optional(), + fieldWithPath("terms[].termsSno").type(JsonFieldType.NUMBER).description("약관 식별번호"), + fieldWithPath("terms[].agreeYn").type(JsonFieldType.STRING).description("약관 동의여부") + ) + ) + ) + .andExpect(status().isCreated()); + } + + +} diff --git a/common/util/src/main/java/kr/co/palnet/kac/util/EncryptUtil.java b/common/util/src/main/java/kr/co/palnet/kac/util/EncryptUtil.java index 26d4396..f495b77 100644 --- a/common/util/src/main/java/kr/co/palnet/kac/util/EncryptUtil.java +++ b/common/util/src/main/java/kr/co/palnet/kac/util/EncryptUtil.java @@ -1,5 +1,6 @@ package kr.co.palnet.kac.util; +import kr.co.palnet.kac.util.kisa.KISA_SHA256; import lombok.extern.slf4j.Slf4j; import javax.crypto.Cipher; @@ -72,6 +73,18 @@ public class EncryptUtil { return encrypted; } + public static String sha256Encrypt(String str) { + + byte[] bytes = str.getBytes(); + byte[] pszDigest = new byte[32]; + KISA_SHA256.SHA256_Encrpyt(bytes, bytes.length, pszDigest); + StringBuffer encrypted = new StringBuffer(); + for (int i = 0; i < 32; i++) { + encrypted.append(String.format("%02x", pszDigest[i])); + } + return encrypted.toString(); + } + public static void main(String[] args) { String key = "1234567890123456"; String initVector = "1234567890123456"; diff --git a/data/pty/src/main/java/kr/co/palnet/kac/data/pty/model/PtyCstmrDtl.java b/data/pty/src/main/java/kr/co/palnet/kac/data/pty/model/PtyCstmrDtl.java index 49acafc..ff288e5 100644 --- a/data/pty/src/main/java/kr/co/palnet/kac/data/pty/model/PtyCstmrDtl.java +++ b/data/pty/src/main/java/kr/co/palnet/kac/data/pty/model/PtyCstmrDtl.java @@ -5,6 +5,7 @@ import lombok.*; import java.time.Instant; import java.time.LocalDate; +import java.time.LocalDateTime; @Data @@ -74,7 +75,7 @@ public class PtyCstmrDtl { // 수정일시 @Column(name = "UPDATE_DT", columnDefinition = "datetime", nullable = false) - private Instant updateDt; + private LocalDateTime updateDt; // 수정사용자ID @Column(name = "UPDATE_USER_ID", length = 30, nullable = false) diff --git a/data/pty/src/main/java/kr/co/palnet/kac/data/pty/model/PtyCstmrGroup.java b/data/pty/src/main/java/kr/co/palnet/kac/data/pty/model/PtyCstmrGroup.java index 8fbc65a..2bdbe8b 100644 --- a/data/pty/src/main/java/kr/co/palnet/kac/data/pty/model/PtyCstmrGroup.java +++ b/data/pty/src/main/java/kr/co/palnet/kac/data/pty/model/PtyCstmrGroup.java @@ -4,6 +4,7 @@ import jakarta.persistence.*; import lombok.*; import java.time.Instant; +import java.time.LocalDateTime; @Data @@ -17,6 +18,7 @@ public class PtyCstmrGroup { // 고객그룹일련번호 @Id @Column(name = "CSTMR_GROUP_SNO") // mysql :: "int unsigned" + @GeneratedValue(strategy = GenerationType.IDENTITY) private Long cstmrGroupSno; // 고객일련번호 @@ -41,7 +43,7 @@ public class PtyCstmrGroup { // 승인일자 @Column(name = "APRVL_DT", columnDefinition = "datetime(6)") - private Instant aprvlDt; + private LocalDateTime aprvlDt; // 참여여부 @Column(name = "JOIN_YN", columnDefinition = "char(1) default 'N'", nullable = false) @@ -53,7 +55,7 @@ public class PtyCstmrGroup { // 탈퇴일시 @Column(name = "WTHDRW_DT", columnDefinition = "datetime(6)") - private Instant wthdrwDt; + private LocalDateTime wthdrwDt; // 터미널ID @Column(name = "TRMNL_ID", length = 20) diff --git a/data/pty/src/main/java/kr/co/palnet/kac/data/pty/model/PtyTermsAgreeTxn.java b/data/pty/src/main/java/kr/co/palnet/kac/data/pty/model/PtyTermsAgreeTxn.java index 3ee413e..3a6a89d 100644 --- a/data/pty/src/main/java/kr/co/palnet/kac/data/pty/model/PtyTermsAgreeTxn.java +++ b/data/pty/src/main/java/kr/co/palnet/kac/data/pty/model/PtyTermsAgreeTxn.java @@ -4,6 +4,7 @@ import jakarta.persistence.*; import lombok.*; import java.time.Instant; +import java.time.LocalDateTime; @Data @@ -40,7 +41,7 @@ public class PtyTermsAgreeTxn { // 동의일시 @Column(name = "AGREE_DT", columnDefinition = "datetime") - private Instant agreeDt; + private LocalDateTime agreeDt; // 처리IP주소 @Column(name = "PROC_IP", length = 39) @@ -48,7 +49,7 @@ public class PtyTermsAgreeTxn { // 수정일시 @Column(name = "UPDATE_DT", columnDefinition = "datetime", nullable = false) - private Instant updateDt; + private LocalDateTime updateDt; // 수정사용자ID @Column(name = "UPDATE_USER_ID", length = 30, nullable = false) diff --git a/data/pty/src/main/java/kr/co/palnet/kac/data/pty/repository/PtyCstmrBasRepository.java b/data/pty/src/main/java/kr/co/palnet/kac/data/pty/repository/PtyCstmrBasRepository.java index dd965dc..58e23d6 100644 --- a/data/pty/src/main/java/kr/co/palnet/kac/data/pty/repository/PtyCstmrBasRepository.java +++ b/data/pty/src/main/java/kr/co/palnet/kac/data/pty/repository/PtyCstmrBasRepository.java @@ -5,7 +5,7 @@ import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; -public interface PtyCstmrBasRepository extends JpaRepository { +public interface PtyCstmrBasRepository extends JpaRepository { @Query("select b from PtyCstmrBas b left join b.ptyCstmrDtl where b.userId = :userId") PtyCstmrBas findByUserId(@Param("userId") String userId); } diff --git a/data/pty/src/main/java/kr/co/palnet/kac/data/pty/repository/PtyCstmrDtlRepository.java b/data/pty/src/main/java/kr/co/palnet/kac/data/pty/repository/PtyCstmrDtlRepository.java index 820c96a..d532daf 100644 --- a/data/pty/src/main/java/kr/co/palnet/kac/data/pty/repository/PtyCstmrDtlRepository.java +++ b/data/pty/src/main/java/kr/co/palnet/kac/data/pty/repository/PtyCstmrDtlRepository.java @@ -3,6 +3,6 @@ package kr.co.palnet.kac.data.pty.repository; import kr.co.palnet.kac.data.pty.model.PtyCstmrDtl; import org.springframework.data.jpa.repository.JpaRepository; -public interface PtyCstmrDtlRepository extends JpaRepository { +public interface PtyCstmrDtlRepository extends JpaRepository { } diff --git a/data/pty/src/main/java/kr/co/palnet/kac/data/pty/repository/PtyCstmrGroupRepository.java b/data/pty/src/main/java/kr/co/palnet/kac/data/pty/repository/PtyCstmrGroupRepository.java index 693ab43..ec2b996 100644 --- a/data/pty/src/main/java/kr/co/palnet/kac/data/pty/repository/PtyCstmrGroupRepository.java +++ b/data/pty/src/main/java/kr/co/palnet/kac/data/pty/repository/PtyCstmrGroupRepository.java @@ -2,7 +2,19 @@ package kr.co.palnet.kac.data.pty.repository; import kr.co.palnet.kac.data.pty.model.PtyCstmrGroup; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; +import java.util.List; +import java.util.Optional; + +@Repository public interface PtyCstmrGroupRepository extends JpaRepository { + public Optional> findByCstmrSnoAndJoinYn(Long cstmrSno, String joinYn); + + public Optional> findByGroupId(String groupId); + + public Optional> findByCstmrSno(Long cstmrSno); + + public Optional findByGroupIdAndCstmrSno(String groupId, Long cstmrSno); } diff --git a/data/pty/src/main/java/kr/co/palnet/kac/data/pty/repository/PtyGroupBasRepository.java b/data/pty/src/main/java/kr/co/palnet/kac/data/pty/repository/PtyGroupBasRepository.java index 3e8a08c..d21ed3f 100644 --- a/data/pty/src/main/java/kr/co/palnet/kac/data/pty/repository/PtyGroupBasRepository.java +++ b/data/pty/src/main/java/kr/co/palnet/kac/data/pty/repository/PtyGroupBasRepository.java @@ -2,7 +2,9 @@ package kr.co.palnet.kac.data.pty.repository; import kr.co.palnet.kac.data.pty.model.PtyGroupBas; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; +@Repository public interface PtyGroupBasRepository extends JpaRepository { } diff --git a/data/pty/src/main/java/kr/co/palnet/kac/data/pty/service/PtyCstmrDomainService.java b/data/pty/src/main/java/kr/co/palnet/kac/data/pty/service/PtyCstmrDomainService.java index 47e429b..ff935e4 100644 --- a/data/pty/src/main/java/kr/co/palnet/kac/data/pty/service/PtyCstmrDomainService.java +++ b/data/pty/src/main/java/kr/co/palnet/kac/data/pty/service/PtyCstmrDomainService.java @@ -1,19 +1,46 @@ package kr.co.palnet.kac.data.pty.service; import kr.co.palnet.kac.data.pty.model.PtyCstmrBas; +import kr.co.palnet.kac.data.pty.model.PtyCstmrDtl; import kr.co.palnet.kac.data.pty.repository.PtyCstmrBasRepository; +import kr.co.palnet.kac.data.pty.repository.PtyCstmrDtlRepository; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; +import java.util.Optional; + @Slf4j @RequiredArgsConstructor @Service public class PtyCstmrDomainService { private final PtyCstmrBasRepository ptyCstmrBasRepository; + private final PtyCstmrDtlRepository ptyCstmrDtlRepository; + + + public PtyCstmrBas getCstmrInfoByUserId(String userId) { return ptyCstmrBasRepository.findByUserId(userId); } + public Optional findPtyCstmrBasById(Long cstmrSno){ + return ptyCstmrBasRepository.findById(cstmrSno); + } + + public PtyCstmrBas savePtyCstmrBas(PtyCstmrBas entity) { + return ptyCstmrBasRepository.save(entity); + } + + public Optional findPtyCstmrDtlById(Long cstmrSno){ + return ptyCstmrDtlRepository.findById(cstmrSno); + } + public PtyCstmrDtl savePtyCstmrDtl(PtyCstmrDtl entity){ + return ptyCstmrDtlRepository.save(entity); + } + + + + + } diff --git a/data/pty/src/main/java/kr/co/palnet/kac/data/pty/service/PtyGroupDomainService.java b/data/pty/src/main/java/kr/co/palnet/kac/data/pty/service/PtyGroupDomainService.java new file mode 100644 index 0000000..6beada4 --- /dev/null +++ b/data/pty/src/main/java/kr/co/palnet/kac/data/pty/service/PtyGroupDomainService.java @@ -0,0 +1,53 @@ +package kr.co.palnet.kac.data.pty.service; + +import kr.co.palnet.kac.data.pty.model.PtyCstmrGroup; +import kr.co.palnet.kac.data.pty.model.PtyGroupBas; +import kr.co.palnet.kac.data.pty.repository.PtyCstmrGroupRepository; +import kr.co.palnet.kac.data.pty.repository.PtyGroupBasRepository; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.Optional; + +@Slf4j +@RequiredArgsConstructor +@Service +public class PtyGroupDomainService { + + private final PtyGroupBasRepository ptyGroupBasRepository; + + private final PtyCstmrGroupRepository ptyCstmrGroupRepository; + + public Optional> findJoinGroupByCstmrSno(Long cstmrSno){ + return ptyCstmrGroupRepository.findByCstmrSnoAndJoinYn(cstmrSno, "Y"); + } + + public Optional> findByGroupId(String groupId){ + return ptyCstmrGroupRepository.findByGroupId(groupId); + } + + public Optional> findByCstmrSno(Long cstmrSno){ + return ptyCstmrGroupRepository.findByCstmrSno(cstmrSno); + } + + public Optional findByGroupIdAndCstmrSno(String groupId, Long cstmrSno){ + return ptyCstmrGroupRepository.findByGroupIdAndCstmrSno(groupId, cstmrSno); + } + + public PtyCstmrGroup savePtyCstmrGroup(PtyCstmrGroup entity){ + return ptyCstmrGroupRepository.save(entity); + } + + public PtyGroupBas findById(String id){ + return ptyGroupBasRepository.findById(id).orElse(null); + } + + public PtyGroupBas savePtyGroupBas(PtyGroupBas entity){ + return ptyGroupBasRepository.save(entity); + } + + + +} diff --git a/data/pty/src/main/java/kr/co/palnet/kac/data/pty/service/PtyTermsDomainService.java b/data/pty/src/main/java/kr/co/palnet/kac/data/pty/service/PtyTermsDomainService.java new file mode 100644 index 0000000..c7e6b93 --- /dev/null +++ b/data/pty/src/main/java/kr/co/palnet/kac/data/pty/service/PtyTermsDomainService.java @@ -0,0 +1,19 @@ +package kr.co.palnet.kac.data.pty.service; + +import kr.co.palnet.kac.data.pty.model.PtyTermsAgreeTxn; +import kr.co.palnet.kac.data.pty.repository.PtyTermsAgreeTxnRepository; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +@Slf4j +@RequiredArgsConstructor +@Service +public class PtyTermsDomainService { + + private final PtyTermsAgreeTxnRepository ptyTermsAgreeTxnRepository; + + public PtyTermsAgreeTxn savePtyTermsAgreeTxn(PtyTermsAgreeTxn entity){ + return ptyTermsAgreeTxnRepository.save(entity); + } +} diff --git a/web/api-user/build.gradle b/web/api-user/build.gradle index acc95bc..82be3ba 100644 --- a/web/api-user/build.gradle +++ b/web/api-user/build.gradle @@ -3,6 +3,7 @@ dependencies { implementation "$boot:spring-boot-starter-web" implementation "$boot:spring-boot-starter-data-jpa" + implementation "$boot:spring-boot-starter-security" // for paging // implementation("org.springframework.data:spring-data-commons") @@ -10,6 +11,7 @@ dependencies { compileOnly 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.2.0' implementation project(":data:pty") implementation project(":common:core") + implementation project(":common:util") compileOnly project(":web:security") } diff --git a/web/api-user/src/main/java/kr/co/palnet/kac/api/v1/user/account/controller/UserAccountController.java b/web/api-user/src/main/java/kr/co/palnet/kac/api/v1/user/account/controller/UserAccountController.java new file mode 100644 index 0000000..6c37293 --- /dev/null +++ b/web/api-user/src/main/java/kr/co/palnet/kac/api/v1/user/account/controller/UserAccountController.java @@ -0,0 +1,74 @@ +package kr.co.palnet.kac.api.v1.user.account.controller; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import kr.co.palnet.kac.api.v1.user.account.model.detail.SearchUserRS; +import kr.co.palnet.kac.api.v1.user.account.model.register.FormRegisterRQ; +import kr.co.palnet.kac.api.v1.user.account.model.update.UpdatePasswordRQ; +import kr.co.palnet.kac.api.v1.user.account.model.update.UpdateUserRQ; +import kr.co.palnet.kac.api.v1.user.account.service.UserAccountService; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +@RestController +@Slf4j +@RequiredArgsConstructor +@RequestMapping("/v1/user/account") +@Tag(name = "유저 - 계정", description = "계정 관련 API") +public class UserAccountController { + + private final UserAccountService userAccountService; + + @PostMapping("/register") + @Operation(summary = "회원가입", description = "유저의 계정을 추가합니다.") + public ResponseEntity createUser(@RequestBody FormRegisterRQ rq){ + + userAccountService.createUser(rq); + + return ResponseEntity.status(HttpStatus.CREATED).build(); + } + + @DeleteMapping("/delete") + @Operation(summary = "회원탈퇴", description = "유저의 계정을 탈퇴시키며 참여한 그룹도 탈퇴시킵니다.") + public ResponseEntity deleteUser(){ + + userAccountService.deleteUser(); + + return ResponseEntity.ok().build(); + } + + @GetMapping("/profile") + @Operation(summary = "회원정보 조회", description = "회원 정보를 조회합니다.") + public ResponseEntity getUserInfo(){ + + SearchUserRS result = userAccountService.getUserInfo(); + + return ResponseEntity.ok().body(result); + } + + @PutMapping("/update/pswd") + @Operation(summary = "회원암호 변경", description = "회원 암호를 변경합니다.") + public ResponseEntity updatePassword(@RequestBody UpdatePasswordRQ rq){ + + userAccountService.updatePassword(rq); + + return ResponseEntity.ok().build(); + } + + @PutMapping("/update") + @Operation(summary = "회원정보 변경", description = "회원의 정보를 수정합니다.") + public ResponseEntity updateUser(@RequestBody UpdateUserRQ rq){ + + userAccountService.updateUser(rq); + + return ResponseEntity.ok().build(); + } + + + + + +} diff --git a/web/api-user/src/main/java/kr/co/palnet/kac/api/v1/user/account/model/PtyCstmrDTO.java b/web/api-user/src/main/java/kr/co/palnet/kac/api/v1/user/account/model/PtyCstmrDTO.java new file mode 100644 index 0000000..36c8a7b --- /dev/null +++ b/web/api-user/src/main/java/kr/co/palnet/kac/api/v1/user/account/model/PtyCstmrDTO.java @@ -0,0 +1,84 @@ +package kr.co.palnet.kac.api.v1.user.account.model; + +import kr.co.palnet.kac.data.pty.model.PtyCstmrBas; +import lombok.Data; + +import java.time.LocalDateTime; + +@Data +public class PtyCstmrDTO { + + private Long cstmrSno; + + private String authId; + + private String cstmrDivCd; + + private String cstmrStatusCd; + + private LocalDateTime cstmrStatusCngDt; + + private String cptAuthCode; + + private String userId; + + private LocalDateTime joinDt; + + private String joinIp; + + private String siteCode; + + private String memberDivCd; + + private String userPswd; + + private LocalDateTime pswdUpdtDt; + + private String rtrshToken; + + private String trmnlId; + + public static PtyCstmrBas toEntity(PtyCstmrDTO dto){ + return PtyCstmrBas.builder() + .cstmrSno(dto.getCstmrSno()) + .authId(dto.getAuthId()) + .cstmrDivCd(dto.getCstmrDivCd()) + .cstmrStatusCd(dto.getCstmrStatusCd()) + .cstmrStatusCngDt(dto.getCstmrStatusCngDt()) + .cptAuthCode(dto.getCptAuthCode()) + .userId(dto.getUserId()) + .joinDt(dto.getJoinDt()) + .joinIp(dto.getJoinIp()) + .siteCode(dto.getSiteCode()) + .memberDivCd(dto.getMemberDivCd()) + .userPswd(dto.getUserPswd()) + .pswdUpdtDt(dto.getPswdUpdtDt()) + .rfrshToken(dto.getRtrshToken()) + .trmnlId(dto.getTrmnlId()) + .build(); + } + + public static PtyCstmrDTO toDto(PtyCstmrBas entity){ + PtyCstmrDTO dto = new PtyCstmrDTO(); + dto.setCstmrSno(entity.getCstmrSno()); + dto.setAuthId(entity.getAuthId()); + dto.setCstmrDivCd(entity.getCstmrDivCd()); + dto.setCstmrStatusCd(entity.getCstmrStatusCd()); + dto.setCstmrStatusCngDt(entity.getCstmrStatusCngDt()); + dto.setCptAuthCode(entity.getCptAuthCode()); + dto.setUserId(entity.getUserId()); + dto.setJoinDt(entity.getJoinDt()); + dto.setJoinIp(entity.getJoinIp()); + dto.setSiteCode(entity.getSiteCode()); + dto.setMemberDivCd(entity.getMemberDivCd()); + dto.setUserPswd(entity.getUserPswd()); + dto.setPswdUpdtDt(entity.getPswdUpdtDt()); + dto.setRtrshToken(entity.getRfrshToken()); + dto.setTrmnlId(entity.getTrmnlId()); + + return dto; + } + + + +} diff --git a/web/api-user/src/main/java/kr/co/palnet/kac/api/v1/user/account/model/PtyCstmrDtlDTO.java b/web/api-user/src/main/java/kr/co/palnet/kac/api/v1/user/account/model/PtyCstmrDtlDTO.java new file mode 100644 index 0000000..4eccb49 --- /dev/null +++ b/web/api-user/src/main/java/kr/co/palnet/kac/api/v1/user/account/model/PtyCstmrDtlDTO.java @@ -0,0 +1,63 @@ +package kr.co.palnet.kac.api.v1.user.account.model; + +import kr.co.palnet.kac.data.pty.model.PtyCstmrDtl; +import lombok.Data; + +import java.time.LocalDate; +import java.time.LocalDateTime; + +@Data +public class PtyCstmrDtlDTO { + + private Long cstmrSno; + + private String ipinDi; + + private String ipinCi; + + private String joinCrtfyCd; + + private String cntryCd; + + private String genderCd; + + private String memberName; + + private LocalDate brthdyDate; + + private String email; + + private String hpno; + + private String clncd; + + private String addr; + + private String addrDtlCn; + + private String zip; + + private LocalDateTime updateDt; + + private String updateUserId; + + public static PtyCstmrDtl toEntity(PtyCstmrDtlDTO dto){ + return PtyCstmrDtl.builder() + .cstmrSno(dto.getCstmrSno()) + .ipinCi(dto.getIpinCi()) + .ipinDi(dto.getIpinDi()) + .joinCrtfyCd(dto.getJoinCrtfyCd()) + .cntryCd(dto.getCntryCd()) + .genderCd(dto.getGenderCd()) + .memberName(dto.getMemberName()) + .brthdyDate(dto.getBrthdyDate()) + .email(dto.getEmail()) + .hpno(dto.getHpno()) + .clncd(dto.getClncd()) + .updateDt(dto.getUpdateDt()) + .updateUserId(dto.getUpdateUserId()) + .build(); + } + + +} diff --git a/web/api-user/src/main/java/kr/co/palnet/kac/api/v1/user/account/model/detail/SearchUserRS.java b/web/api-user/src/main/java/kr/co/palnet/kac/api/v1/user/account/model/detail/SearchUserRS.java new file mode 100644 index 0000000..595256d --- /dev/null +++ b/web/api-user/src/main/java/kr/co/palnet/kac/api/v1/user/account/model/detail/SearchUserRS.java @@ -0,0 +1,40 @@ +package kr.co.palnet.kac.api.v1.user.account.model.detail; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDate; +import java.time.LocalDateTime; + +@Data +public class SearchUserRS { + + @Schema(description = "이름" , example = "이경도") + private String memberName; + + @Schema(description = "생년월일" , example = "1999-09-07") + private LocalDate brthdyDate; + + @Schema(description = "국적코드" , example = "KOR") + private String cntryCd; + + @Schema(description = "이메일" , example = "lkd9125@naver.com") + private String email; + + @Schema(description = "휴대폰번호" , example = "01083703435") + private String hpno; + + @Schema(description = "ID" , example = "lkd9125") + private String userId; + + @Schema(description = "최종 업데이트 일시" , example = "2024-02-19T16:40:33.000") + private LocalDateTime updateDt; + + @Schema(description = "최종 업데이트 유저" , example = "lkd9125") + private String updateuserId; + + @Schema(description = "유저 청 구분코드" , example = "KAC") + private String cptAuthCode; +} diff --git a/web/api-user/src/main/java/kr/co/palnet/kac/api/v1/user/account/model/register/AgreeTermsModel.java b/web/api-user/src/main/java/kr/co/palnet/kac/api/v1/user/account/model/register/AgreeTermsModel.java new file mode 100644 index 0000000..a2ee415 --- /dev/null +++ b/web/api-user/src/main/java/kr/co/palnet/kac/api/v1/user/account/model/register/AgreeTermsModel.java @@ -0,0 +1,14 @@ +package kr.co.palnet.kac.api.v1.user.account.model.register; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Data +public class AgreeTermsModel { + + @Schema(description = "약관 일련번호", example = "1") + private Long termsSno; + @Schema(description = "동의여부", example = "Y") + private String agreeYn; + +} diff --git a/web/api-user/src/main/java/kr/co/palnet/kac/api/v1/user/account/model/register/FormRegisterRQ.java b/web/api-user/src/main/java/kr/co/palnet/kac/api/v1/user/account/model/register/FormRegisterRQ.java new file mode 100644 index 0000000..05d51a1 --- /dev/null +++ b/web/api-user/src/main/java/kr/co/palnet/kac/api/v1/user/account/model/register/FormRegisterRQ.java @@ -0,0 +1,111 @@ +package kr.co.palnet.kac.api.v1.user.account.model.register; + +import io.swagger.v3.oas.annotations.media.Schema; +import kr.co.palnet.kac.api.v1.user.account.model.PtyCstmrDTO; +import kr.co.palnet.kac.api.v1.user.account.model.PtyCstmrDtlDTO; +import kr.co.palnet.kac.util.HttpUtils; +import lombok.Data; + +import java.time.LocalDate; +import java.time.LocalDateTime; + +@Data +public class FormRegisterRQ { + + @Schema(description = "고객구분코드" , example = "MEMBER") + private String cstrmDivCd; + + @Schema(description = "고객상태코드" , example = "A") + private String cstrmStatusCd; + + @Schema(description = "유저 아이디(중복인 경우 숫자 변경)" , example = "tester01") + private String userId; + + @Schema(description = "유저 권한" , example = "USER") + private String authId; + + @Schema(description = "사이트 코드" , example = "DRON") + private String siteCode; + + @Schema(description = "유저 비밀번호" , example = "test1234") + private String userPswd; + + @Schema(description = "가입인증 수단 코드" , example = "HP_CRTFD") + private String joinCrtfyCd; + + @Schema(description = "멤버 이름" , example = "TESTER") + private String memberName; + + @Schema(description = "생년월일", example = "1997-05-05", implementation = String.class) + private LocalDate brthdyDate; + + @Schema(description = "이메일" , example = "tester@test.co.kr") + private String email; + + @Schema(description = "멤버 휴대폰번호" , example = "01012345678") + private String hpno; + + @Schema(description = "국가 코드" , example = "+82") + private String clncd; + + private AgreeTermsModel[] terms; + + @Schema(description = "권한코드(부서)" , example = "KAC") + private String cptAuthCode; + +// @Schema(hidden = true) +// private String memberDivCd; + + @Schema(hidden = true) + private String ipinDi; + + @Schema(hidden = true) + private String ipinCi; + + @Schema(description = "국가코드" , example = "KOR") + private String cntryCd; + + @Schema(description = "성별코드" , example = "M") + private String genderCd; + +// @Schema(hidden = true) +// private Instant testDt; + +// @Schema(hidden = true) +// private String trmnlId; + + public static PtyCstmrDTO toBasicDto(FormRegisterRQ rq){ + PtyCstmrDTO dto = new PtyCstmrDTO(); + dto.setCstmrDivCd(rq.getCstrmDivCd()); + dto.setCstmrStatusCd(rq.getCstrmStatusCd()); + dto.setUserId(rq.getUserId()); + dto.setAuthId(rq.getAuthId()); + dto.setSiteCode(rq.getSiteCode()); + dto.setUserPswd(rq.getUserPswd()); + dto.setJoinDt(LocalDateTime.now()); + dto.setJoinIp(HttpUtils.getRequestIp()); + dto.setCptAuthCode(rq.getCptAuthCode() == null ? "KAC": rq.getCptAuthCode()); + + return dto; + } + + public static PtyCstmrDtlDTO toDetailDto(FormRegisterRQ rq, Long cstmrSno){ + PtyCstmrDtlDTO dto = new PtyCstmrDtlDTO(); + dto.setCstmrSno(cstmrSno); + dto.setIpinCi(rq.getIpinCi()); + dto.setIpinDi(rq.getIpinDi()); + dto.setJoinCrtfyCd(rq.getJoinCrtfyCd()); + dto.setCntryCd(rq.getCntryCd() == null || rq.getCntryCd().isEmpty() ? "KOR" : rq.getCntryCd()); + dto.setGenderCd(rq.getGenderCd()); + dto.setMemberName(rq.getMemberName()); + dto.setBrthdyDate(rq.getBrthdyDate()); + dto.setEmail(rq.getEmail()); + dto.setHpno(rq.getHpno()); + dto.setClncd(rq.getClncd()); + dto.setUpdateDt(LocalDateTime.now()); + dto.setUpdateUserId(rq.getUserId()); + + return dto; + } + +} diff --git a/web/api-user/src/main/java/kr/co/palnet/kac/api/v1/user/account/model/update/UpdatePasswordRQ.java b/web/api-user/src/main/java/kr/co/palnet/kac/api/v1/user/account/model/update/UpdatePasswordRQ.java new file mode 100644 index 0000000..b04658c --- /dev/null +++ b/web/api-user/src/main/java/kr/co/palnet/kac/api/v1/user/account/model/update/UpdatePasswordRQ.java @@ -0,0 +1,19 @@ +package kr.co.palnet.kac.api.v1.user.account.model.update; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Data +public class UpdatePasswordRQ { + + // TODO :: 해당 컬럼은 Api실행시 로직상에서도 필요하지 않을뿐더러 클라이언트에서도 사용되지 않고있음 + @Schema(description = "유저의 기존 비밀번호", example = "palnet!234") + private String userPswd; + + @Schema(description = "유저의 새로운 비밀번호", example = "palnet1234") + private String newPswd; + + @Schema(description = "유저의 새로운 비밀번호(확인)", example = "palnet1234") + private String newPswdConfirm; + +} diff --git a/web/api-user/src/main/java/kr/co/palnet/kac/api/v1/user/account/model/update/UpdateUserRQ.java b/web/api-user/src/main/java/kr/co/palnet/kac/api/v1/user/account/model/update/UpdateUserRQ.java new file mode 100644 index 0000000..354dd5a --- /dev/null +++ b/web/api-user/src/main/java/kr/co/palnet/kac/api/v1/user/account/model/update/UpdateUserRQ.java @@ -0,0 +1,15 @@ +package kr.co.palnet.kac.api.v1.user.account.model.update; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Data +public class UpdateUserRQ { + + @Schema(description = "유저 이메일" , example = "updateEmail@test.co.kr") + private String email; + + @Schema(description = "업데이트할 핸드폰 번호", example = "01023457777") + private String hpno; + +} diff --git a/web/api-user/src/main/java/kr/co/palnet/kac/api/v1/user/account/service/UserAccountService.java b/web/api-user/src/main/java/kr/co/palnet/kac/api/v1/user/account/service/UserAccountService.java new file mode 100644 index 0000000..900e7a0 --- /dev/null +++ b/web/api-user/src/main/java/kr/co/palnet/kac/api/v1/user/account/service/UserAccountService.java @@ -0,0 +1,249 @@ +package kr.co.palnet.kac.api.v1.user.account.service; + +import kr.co.palnet.kac.api.v1.user.account.model.PtyCstmrDTO; +import kr.co.palnet.kac.api.v1.user.account.model.PtyCstmrDtlDTO; +import kr.co.palnet.kac.api.v1.user.account.model.detail.SearchUserRS; +import kr.co.palnet.kac.api.v1.user.account.model.register.FormRegisterRQ; +import kr.co.palnet.kac.api.v1.user.account.model.register.AgreeTermsModel; +import kr.co.palnet.kac.api.v1.user.account.model.update.UpdatePasswordRQ; +import kr.co.palnet.kac.api.v1.user.account.model.update.UpdateUserRQ; +import kr.co.palnet.kac.config.security.util.SessionHelper; +import kr.co.palnet.kac.core.exception.BaseErrorCode; +import kr.co.palnet.kac.core.exception.BaseException; +import kr.co.palnet.kac.data.pty.model.*; +import kr.co.palnet.kac.data.pty.service.PtyCstmrDomainService; +import kr.co.palnet.kac.data.pty.service.PtyGroupDomainService; +import kr.co.palnet.kac.data.pty.service.PtyTermsDomainService; +import kr.co.palnet.kac.util.EncryptUtil; +import kr.co.palnet.kac.util.HttpUtils; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.time.LocalDateTime; +import java.util.List; +import java.util.Optional; + +@Service +@Slf4j +@RequiredArgsConstructor +public class UserAccountService { + + private final PtyCstmrDomainService ptyCstmrDomainService; + + private final PtyGroupDomainService ptyGroupDomainService; + + private final PtyTermsDomainService ptyTermsDomainService; + + private final PasswordEncoder passwordEncoder; + + @Transactional + public void createUser(FormRegisterRQ rq) { + + PtyCstmrBas registeredUser = ptyCstmrDomainService.getCstmrInfoByUserId(rq.getUserId()); + if(registeredUser != null) throw new BaseException(BaseErrorCode.DATA_ALREADY_EXISTS); + + rq.setHpno(rq.getHpno().replaceAll("-", "")); + + //처리 1. 민감정보 암호화 처리(비밀번호 , 이름 , 휴대폰번호 , 이메일) + rq.setUserPswd(passwordEncoder.encode(rq.getUserPswd())); + rq.setHpno(EncryptUtil.encrypt(rq.getHpno())); + rq.setEmail(EncryptUtil.encrypt(rq.getEmail())); + + //처리 2. 마스터 정보 저장 + PtyCstmrDTO basicDto = FormRegisterRQ.toBasicDto(rq); + PtyCstmrBas basEntity = ptyCstmrDomainService.savePtyCstmrBas(PtyCstmrDTO.toEntity(basicDto)); + + if(basEntity == null) { + throw new BaseException(BaseErrorCode.NOT_PROCESS); + } + + //처리 3. 상세 정보 저장 + PtyCstmrDtlDTO detailDto = FormRegisterRQ.toDetailDto(rq, basEntity.getCstmrSno()); + ptyCstmrDomainService.savePtyCstmrDtl(PtyCstmrDtlDTO.toEntity(detailDto)); + + //처리 4. 약관 동의 정보 저장 + if(rq.getTerms() != null && rq.getTerms().length > 0){ + for(AgreeTermsModel model : rq.getTerms()){ + PtyTermsAgreeTxn agreeEntity = new PtyTermsAgreeTxn(); + agreeEntity.setCstmrSno(basEntity.getCstmrSno()); + agreeEntity.setProcIp(HttpUtils.getRequestIp()); + agreeEntity.setTermsSno(model.getTermsSno()); + agreeEntity.setUpdateDt(LocalDateTime.now() ); + agreeEntity.setUpdateUserId(basEntity.getUserId()); + agreeEntity.setAgreeYn(model.getAgreeYn()); + if(model.getAgreeYn().equals("Y")) { + agreeEntity.setAgreeDt(LocalDateTime.now() ); + } + + ptyTermsDomainService.savePtyTermsAgreeTxn(agreeEntity); + } + } + + } + + @Transactional + public void deleteUser() { + Long cstmrSno = SessionHelper.getCstmrSno(); + + if(cstmrSno == null) return; + + Optional> groupData = ptyGroupDomainService.findJoinGroupByCstmrSno(cstmrSno); + + if(groupData.isPresent() && !groupData.get().isEmpty()){ + + List groupInfo = groupData.get(); + + for(PtyCstmrGroup group : groupInfo) { + // 회원의 그룹 권한이 MASTER 일 경우 + if(group.getGroupAuthCd().equals("MASTER")) { + PtyGroupBas groupEntity = ptyGroupDomainService.findById(group.getGroupId()); + + // 그룹이 있을경우 그룹의 사용여부 "N" 값으로 저장 + if(groupEntity != null) { + groupEntity.setUseYn("N"); + ptyGroupDomainService.savePtyGroupBas(groupEntity); + } + + // 탈퇴하는 회원이 그룹의 MASTER일 경우 그룹 참여자의 Join여부를 N으로 업데이트 함 + Optional> cstmrEntityData = ptyGroupDomainService.findByGroupId(group.getGroupId()); + + // cstmrEntity 값이 있을 경우 참여여부 "N" 값으로 저장 + if(cstmrEntityData.isPresent()) { + + List cstmrEntity = cstmrEntityData.get(); + + for(PtyCstmrGroup cstmr : cstmrEntity) { + cstmr.setJoinYn("N"); + ptyGroupDomainService.savePtyCstmrGroup(cstmr); + } + } + } + + // 회원 고유번호로 데이터베이스에서 그룹참여정보 가져옴 + Optional> aprvlEntityData = ptyGroupDomainService.findByCstmrSno(cstmrSno); + + // AprvlEntity[그룹참여 정보가] 있을경우 + if(aprvlEntityData.isPresent()) { + + List aprvlEntity = aprvlEntityData.get(); + + // 그룹 승인여부를 "N"값으로 저장 + for(PtyCstmrGroup aprvl : aprvlEntity) { + aprvl.setAprvlYn("N"); + aprvl.setAprvlDt(null); + ptyGroupDomainService.savePtyCstmrGroup(aprvl); + } + + // 그룹 참여여부를 "N"값으로 저장 + Optional cstmrEntityData = ptyGroupDomainService.findByGroupIdAndCstmrSno(group.getGroupId(), cstmrSno); + if(cstmrEntityData.isPresent()) { + PtyCstmrGroup cstmrEntity = cstmrEntityData.get(); + + cstmrEntity.setJoinYn("N"); + ptyGroupDomainService.savePtyCstmrGroup(cstmrEntity); + } + } + } + } + + Optional userEntityData = ptyCstmrDomainService.findPtyCstmrBasById(cstmrSno); + + if(userEntityData.isPresent()){ + PtyCstmrBas userEntity = userEntityData.get(); + userEntity.setCstmrStatusCd("W"); + userEntity.setCstmrStatusCngDt(LocalDateTime.now()); + + ptyCstmrDomainService.savePtyCstmrBas(userEntity); + } else { + throw new BaseException(BaseErrorCode.DATA_EMPTY); + } + } + + @Transactional + public SearchUserRS getUserInfo() { + + Long cstmrSno = SessionHelper.getCstmrSno(); + + Optional userEntityData = ptyCstmrDomainService.findPtyCstmrBasById(cstmrSno); + Optional userDetailEntityData = ptyCstmrDomainService.findPtyCstmrDtlById(cstmrSno); + + if(userEntityData.isPresent() && userDetailEntityData.isPresent()){ + PtyCstmrBas userEntity = userEntityData.get(); + PtyCstmrDtl userDetailEntity = userDetailEntityData.get(); + + SearchUserRS result = new SearchUserRS(); + + result.setMemberName(userDetailEntity.getMemberName()); + result.setUserId(userEntity.getUserId()); + result.setBrthdyDate(userDetailEntity.getBrthdyDate()); + result.setCntryCd(userDetailEntity.getCntryCd()); + result.setEmail(EncryptUtil.decrypt(userDetailEntity.getEmail())); + result.setHpno(EncryptUtil.decrypt(userDetailEntity.getHpno())); + result.setUpdateDt(userDetailEntity.getUpdateDt()); + result.setUpdateuserId(userDetailEntity.getUpdateUserId()); + result.setCptAuthCode(userEntity.getCptAuthCode()); + + return result; + } else { + throw new BaseException(BaseErrorCode.DATA_EMPTY); + } + } + + @Transactional + public void updatePassword(UpdatePasswordRQ rq) { + + // 1. 토큰 유저 정보 불러오기 + Long cstmrSno = SessionHelper.getCstmrSno(); + + // 2. DB의 유저정보 조회 + Optional userEntityData = ptyCstmrDomainService.findPtyCstmrBasById(cstmrSno); + + if(userEntityData.isEmpty()) throw new BaseException(BaseErrorCode.DATA_EMPTY); + + // 5. 새로운 비밀번호 검증 + if(!rq.getNewPswd().equals(rq.getNewPswdConfirm())) { + // 5.e 새로운 비밀번호 일치하지 않으면 예외처리 + throw new BaseException(BaseErrorCode.FAILED); //임시...수정필요 + } + + // 6. 새로운 패스워드 암호화 + String encryptNewPwd = passwordEncoder.encode(rq.getNewPswd()); + + PtyCstmrBas userEntity = userEntityData.get(); + + // 7. 유저 정보 저장 + userEntity.setUserPswd(encryptNewPwd); + userEntity.setPswdUpdtDt(LocalDateTime.now()); + + ptyCstmrDomainService.savePtyCstmrBas(userEntity); + } + + + @Transactional + public void updateUser(UpdateUserRQ rq) { + + Long cstmrSno = SessionHelper.getCstmrSno(); + String userId = SessionHelper.getUserId(); + + Optional userEntityData = ptyCstmrDomainService.findPtyCstmrBasById(cstmrSno); + Optional userDetailEntityData = ptyCstmrDomainService.findPtyCstmrDtlById(cstmrSno); + + if(userEntityData.isPresent() && userDetailEntityData.isPresent()){ + PtyCstmrBas userEntity = userEntityData.get(); + PtyCstmrDtl userDetailEntity = userDetailEntityData.get(); + + userDetailEntity.setUpdateDt(LocalDateTime.now()); + userDetailEntity.setUpdateUserId(userId); + if(rq.getEmail() != null) userDetailEntity.setEmail(EncryptUtil.encrypt(rq.getEmail())); + if(rq.getHpno() != null) userDetailEntity.setHpno(EncryptUtil.encrypt(rq.getHpno())); + + userEntity.setPtyCstmrDtl(userDetailEntity); + } else { + throw new BaseException(BaseErrorCode.DATA_EMPTY); + } + + } +} diff --git a/web/api-user/src/main/java/kr/co/palnet/kac/api/v1/user/certificate/controller/UserCertificateController.java b/web/api-user/src/main/java/kr/co/palnet/kac/api/v1/user/certificate/controller/UserCertificateController.java new file mode 100644 index 0000000..99e6ea1 --- /dev/null +++ b/web/api-user/src/main/java/kr/co/palnet/kac/api/v1/user/certificate/controller/UserCertificateController.java @@ -0,0 +1,17 @@ +package kr.co.palnet.kac.api.v1.user.certificate.controller; + +import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RequestMapping +@RestController +@Slf4j +@RequiredArgsConstructor +@Tag(name = "유저 - 인증", description = "유저 인증관련") +public class UserCertificateController { + + +} diff --git a/web/api-user/src/main/java/kr/co/palnet/kac/util/HttpUtils.java b/web/api-user/src/main/java/kr/co/palnet/kac/util/HttpUtils.java new file mode 100644 index 0000000..96fa12d --- /dev/null +++ b/web/api-user/src/main/java/kr/co/palnet/kac/util/HttpUtils.java @@ -0,0 +1,35 @@ +package kr.co.palnet.kac.util; + +import jakarta.servlet.http.HttpServletRequest; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +@Slf4j +public class HttpUtils { + + /** + * 클라이언트 IP 를 가져온다 + * @return 클라이언트 IP + */ + public static String getRequestIp() { + HttpServletRequest req = getCurrentRequest(); + + String[] HEADER_CLIENT_IP = { "NS-CLIENT-IP", "X-Forwarded-For", "Proxy-Client-IP", "WL-Proxy-Client-IP", "HTTP_CLIENT_IP", "HTTP_X_FORWARDED_FOR"}; + for (String name : HEADER_CLIENT_IP) { + String clientIp = req.getHeader(name); + if(!StringUtils.isEmpty(clientIp) && !"unknown".equalsIgnoreCase(clientIp)) { + log.debug("{}={}", name, clientIp); + return clientIp; + } + } + + return req.getRemoteAddr(); + } + + public static HttpServletRequest getCurrentRequest() { + ServletRequestAttributes sra = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); + return sra.getRequest(); + } +} diff --git a/web/security/src/main/java/kr/co/palnet/kac/config/security/SecurityConfig.java b/web/security/src/main/java/kr/co/palnet/kac/config/security/SecurityConfig.java index 2d08f82..0229305 100644 --- a/web/security/src/main/java/kr/co/palnet/kac/config/security/SecurityConfig.java +++ b/web/security/src/main/java/kr/co/palnet/kac/config/security/SecurityConfig.java @@ -17,6 +17,7 @@ import org.springframework.security.config.annotation.web.configuration.EnableWe import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer; import org.springframework.security.config.annotation.web.configurers.RequestCacheConfigurer; import org.springframework.security.config.http.SessionCreationPolicy; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.password.NoOpPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.web.SecurityFilterChain; @@ -52,9 +53,9 @@ public abstract class SecurityConfig { @Bean PasswordEncoder passwordEncoder() { -// return new BCryptPasswordEncoder(); + return new BCryptPasswordEncoder(); // TODO 테스트 후 BCryptPasswordEncoder 로 변경 - 회원가입 로직 구현 후 제거 - return NoOpPasswordEncoder.getInstance(); +// return NoOpPasswordEncoder.getInstance(); } @Bean