From 39c6d725e0580e5fbea4c881dbc00a1ee80107e2 Mon Sep 17 00:00:00 2001 From: LeeJE20 <42895142+LeeJE20@users.noreply.github.com> Date: Tue, 1 Aug 2023 20:27:10 +0900 Subject: [PATCH 01/13] =?UTF-8?q?[chore]=20test=20=EB=B8=8C=EB=9E=9C?= =?UTF-8?q?=EC=B9=98=20cicd=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/deploy.yml | 40 ++++++++++++++++++++++++++++++++---- 1 file changed, 36 insertions(+), 4 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 57018759..6e848aca 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -4,9 +4,11 @@ on: push: branches: - main + - test pull_request: branches: - main + - test workflow_dispatch: inputs: @@ -20,6 +22,7 @@ on: env: S3_BUCKET_NAME: wingle-ci-bucket + TEST_S3_BUCKET_NAME: wingle-ci-bucket CODE_DEPLOY_APPLICATION_NAME: wingle-codedeploy-app CODE_DEPLOY_DEPLOYMENT_GROUP_NAME: wingle-codedeploy-group @@ -104,11 +107,11 @@ jobs: shell: bash - name: Make zip file - if: contains(github.ref, 'main') +# if: contains(github.ref, 'main') run: zip -r ./$GITHUB_SHA.zip . shell: bash - - name: Configure AWS credentials + - name: πŸš€ PROD - Configure AWS credentials if: contains(github.ref, 'main') uses: aws-actions/configure-aws-credentials@v1 with: @@ -116,7 +119,7 @@ jobs: aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} aws-region: ${{ secrets.AWS_REGION }} - - name: Upload to AWS S3 + - name: πŸš€ PROD - Upload to AWS S3 if: contains(github.ref, 'main') run: | cd ./wingle @@ -127,7 +130,7 @@ jobs: --source . # S3 버킷에 μžˆλŠ” νŒŒμΌμ„ λŒ€μƒμœΌλ‘œ CodeDeploy μ‹€ν–‰ - - name: Deploy to AWS EC2 from S3 + - name: πŸš€ PROD - Deploy to AWS EC2 from S3 if: contains(github.ref, 'main') run: | aws deploy create-deployment \ @@ -135,3 +138,32 @@ jobs: --deployment-config-name CodeDeployDefault.AllAtOnce \ --deployment-group-name ${{ env.CODE_DEPLOY_DEPLOYMENT_GROUP_NAME }} \ --s3-location bucket=$S3_BUCKET_NAME,key=build/$GITHUB_SHA.zip,bundleType=zip + + + - name: πŸ‘€ TEST - Configure AWS credentials + if: contains(github.ref, 'test') + uses: aws-actions/configure-aws-credentials@v1 + with: + aws-access-key-id: ${{ secrets.TEST_AWS_ACCESS_KEY_ID }} + aws-secret-access-key: ${{ secrets.TEST_AWS_SECRET_ACCESS_KEY }} + aws-region: ${{ secrets.AWS_REGION }} + + - name: πŸ‘€ TEST - Upload to AWS S3 + if: contains(github.ref, 'test') + run: | + cd ./wingle + aws deploy push \ + --application-name ${{ env.CODE_DEPLOY_APPLICATION_NAME }} \ + --ignore-hidden-files \ + --s3-location s3://$TEST_S3_BUCKET_NAME/build/$GITHUB_SHA.zip \ + --source . + + # S3 버킷에 μžˆλŠ” νŒŒμΌμ„ λŒ€μƒμœΌλ‘œ CodeDeploy μ‹€ν–‰ + - name: πŸ‘€ TEST - Deploy to AWS EC2 from S3 + if: contains(github.ref, 'test') + run: | + aws deploy create-deployment \ + --application-name ${{ env.CODE_DEPLOY_APPLICATION_NAME }} \ + --deployment-config-name CodeDeployDefault.AllAtOnce \ + --deployment-group-name ${{ env.CODE_DEPLOY_DEPLOYMENT_GROUP_NAME }} \ + --s3-location bucket=$TEST_S3_BUCKET_NAME,key=build/$GITHUB_SHA.zip,bundleType=zip From 62ee167c6cf9596b072f6ec6cd86d425b4c38b76 Mon Sep 17 00:00:00 2001 From: LeeJE20 <42895142+LeeJE20@users.noreply.github.com> Date: Tue, 1 Aug 2023 20:40:35 +0900 Subject: [PATCH 02/13] =?UTF-8?q?[chore]=20test=20=EC=84=9C=EB=B2=84=20app?= =?UTF-8?q?lication.yml=20=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit stage profile둜 생성 --- .github/workflows/deploy.yml | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 6e848aca..9a478246 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -49,7 +49,7 @@ jobs: restore-keys: | ${{ runner.os }}-gradle- - - name: make main application.yml + - name: πŸš€ PROD - make main application.yml run: | sudo mkdir -p ./wingle/src/main/resources sudo chmod 777 ./wingle/src/main/resources @@ -63,6 +63,20 @@ jobs: path: ./wingle/src/main/resources/application.yml if-no-files-found: 'error' + - name: πŸ‘€ TEST - make stage application.yml + run: | + sudo mkdir -p ./wingle/src/main/resources + sudo chmod 777 ./wingle/src/main/resources + cd ./wingle/src/main/resources + touch ./application.yml + echo "${{ secrets.STAGE_YML }}" > ./application.yml + # 파일 μ—†μœΌλ©΄ λΉŒλ“œ μ—λŸ¬ + - uses: actions/upload-artifact@v3 + with: + name: application.yml + path: ./wingle/src/main/resources/application.yml + if-no-files-found: 'error' + - name: make test application.yml run: | sudo mkdir -p ./wingle/src/test/resources From 2fa3dc97de9f9e00d6f6eafefef08e1a8a9b0c14 Mon Sep 17 00:00:00 2001 From: LeeJE20 <42895142+LeeJE20@users.noreply.github.com> Date: Tue, 1 Aug 2023 21:16:21 +0900 Subject: [PATCH 03/13] =?UTF-8?q?[chore]=20prod,=20test=20=EB=B6=84?= =?UTF-8?q?=EA=B8=B0=EC=B2=98=EB=A6=AC=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/deploy.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 9a478246..4df903b3 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -50,6 +50,7 @@ jobs: ${{ runner.os }}-gradle- - name: πŸš€ PROD - make main application.yml + if: contains(github.ref, 'main') run: | sudo mkdir -p ./wingle/src/main/resources sudo chmod 777 ./wingle/src/main/resources @@ -64,6 +65,7 @@ jobs: if-no-files-found: 'error' - name: πŸ‘€ TEST - make stage application.yml + if: contains(github.ref, 'test') run: | sudo mkdir -p ./wingle/src/main/resources sudo chmod 777 ./wingle/src/main/resources From 979f8854009324889baf766d0e1492186192082d Mon Sep 17 00:00:00 2001 From: LeeJE20 <42895142+LeeJE20@users.noreply.github.com> Date: Tue, 1 Aug 2023 21:18:47 +0900 Subject: [PATCH 04/13] =?UTF-8?q?[chore]=20=EB=A1=9C=EC=A7=81=20=EC=88=9C?= =?UTF-8?q?=EC=84=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit application.yml 생성 이후 쑴재 μ—¬λΆ€ 체크 --- .github/workflows/deploy.yml | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 4df903b3..da0e0a39 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -57,12 +57,6 @@ jobs: cd ./wingle/src/main/resources touch ./application.yml echo "${{ secrets.MAIN_YML }}" > ./application.yml - # 파일 μ—†μœΌλ©΄ λΉŒλ“œ μ—λŸ¬ - - uses: actions/upload-artifact@v3 - with: - name: application.yml - path: ./wingle/src/main/resources/application.yml - if-no-files-found: 'error' - name: πŸ‘€ TEST - make stage application.yml if: contains(github.ref, 'test') @@ -72,6 +66,7 @@ jobs: cd ./wingle/src/main/resources touch ./application.yml echo "${{ secrets.STAGE_YML }}" > ./application.yml + # 파일 μ—†μœΌλ©΄ λΉŒλ“œ μ—λŸ¬ - uses: actions/upload-artifact@v3 with: From 4f3b1ac2815fe570a20796411a642975627d9406 Mon Sep 17 00:00:00 2001 From: minjikim Date: Wed, 2 Aug 2023 02:25:59 +0900 Subject: [PATCH 05/13] =?UTF-8?q?[fix]=20AES256Util=20iv,=20key=20applicat?= =?UTF-8?q?ion.yml=20=EA=B0=92=EC=9C=BC=EB=A1=9C=20=EB=B3=80=EA=B2=BD=20?= =?UTF-8?q?=EB=B0=8F=20salt=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kr/co/wingle/common/util/AES256Util.java | 130 +++++++++++++----- 1 file changed, 97 insertions(+), 33 deletions(-) diff --git a/wingle/src/main/java/kr/co/wingle/common/util/AES256Util.java b/wingle/src/main/java/kr/co/wingle/common/util/AES256Util.java index 068aca1b..7a5acf28 100644 --- a/wingle/src/main/java/kr/co/wingle/common/util/AES256Util.java +++ b/wingle/src/main/java/kr/co/wingle/common/util/AES256Util.java @@ -1,13 +1,16 @@ package kr.co.wingle.common.util; -import java.io.UnsupportedEncodingException; -import java.security.GeneralSecurityException; -import java.security.Key; - import javax.crypto.Cipher; +import javax.crypto.SecretKey; +import javax.crypto.SecretKeyFactory; import javax.crypto.spec.IvParameterSpec; +import javax.crypto.spec.PBEKeySpec; import javax.crypto.spec.SecretKeySpec; +import org.apache.commons.codec.DecoderException; +import org.apache.commons.codec.binary.Base64; +import org.apache.commons.codec.binary.Hex; +import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import kr.co.wingle.common.constants.ErrorCode; @@ -15,45 +18,62 @@ @Component public class AES256Util { - //initial vector μ„€μ • - private static String iv = "0000000000000001"; - private static Key keySpec; - - public AES256Util() throws UnsupportedEncodingException { - iv = iv.substring(0, 16); - byte[] keyBytes = new byte[16]; - byte[] b = iv.getBytes("UTF-8"); - int len = b.length; - if (len > keyBytes.length) { - len = keyBytes.length; - } - System.arraycopy(b, 0, keyBytes, 0, len); - SecretKeySpec _keySpec = new SecretKeySpec(keyBytes, "AES"); - keySpec = _keySpec; + + private static String KEY; + private static byte[] SALT; + private static String IV; + + @Value("${aes256.key}") + public void setKEY(String KEY) { + AES256Util.KEY = KEY; + } + + @Value("${aes256.salt}") + public void setSALT(String SALT) throws DecoderException { + AES256Util.SALT = Hex.decodeHex(SALT.toCharArray()); + } + + @Value("${aes256.iv}") + public void setIV(String IV) { + AES256Util.IV = IV; } - //μ•”ν˜Έν™” public static String encrypt(String str) { try { - Cipher c = Cipher.getInstance("AES/CBC/PKCS5Padding"); - c.init(Cipher.ENCRYPT_MODE, keySpec, new IvParameterSpec((iv.getBytes()))); - byte[] encrypted = c.doFinal(str.getBytes("UTF-8")); - // String enStr = new String(Base64.encodeBase64(encrypted)); - return new java.math.BigInteger(encrypted).toString(16); - } catch (GeneralSecurityException | UnsupportedEncodingException e) { + SecretKey key = generateKey(KEY); + byte[] encrypted = doFinal(Cipher.ENCRYPT_MODE, key, IV, str.getBytes("UTF-8")); + return encodeHex(encrypted); + } catch (Exception e) { + throw new InternalServerErrorException(ErrorCode.ENCRYPT_FAIL); + } + } + + public static String encrypt(String str, String salt) { + try { + SecretKey key = generateKey(KEY, salt); + byte[] encrypted = doFinal(Cipher.ENCRYPT_MODE, key, IV, str.getBytes("UTF-8")); + return encodeHex(encrypted); + } catch (Exception e) { throw new InternalServerErrorException(ErrorCode.ENCRYPT_FAIL); } } - //λ³΅ν˜Έν™” public static String decrypt(String str) { try { - Cipher c = Cipher.getInstance("AES/CBC/PKCS5Padding"); - c.init(Cipher.DECRYPT_MODE, keySpec, new IvParameterSpec(iv.getBytes())); - // byte[] byteStr = Base64.decodeBase64(str.getBytes()); - byte[] byteStr = new java.math.BigInteger(str, 16).toByteArray(); - return new String(c.doFinal(byteStr), "UTF-8"); - } catch (GeneralSecurityException | UnsupportedEncodingException e) { + SecretKey key = generateKey(KEY); + byte[] decrypted = doFinal(Cipher.DECRYPT_MODE, key, IV, decodeBase64(str)); + return new String(decrypted, "UTF-8"); + } catch (Exception e) { + throw new InternalServerErrorException(ErrorCode.DECRYPT_FAIL); + } + } + + public static String decrypt(String str, String salt) { + try { + SecretKey key = generateKey(KEY, salt); + byte[] decrypted = doFinal(Cipher.DECRYPT_MODE, key, IV, decodeBase64(str)); + return new String(decrypted, "UTF-8"); + } catch (Exception e) { throw new InternalServerErrorException(ErrorCode.DECRYPT_FAIL); } } @@ -61,4 +81,48 @@ public static String decrypt(String str) { public static Long userIdDecrypt(String userId) { return Long.parseLong(decrypt(userId)); } + + private static byte[] doFinal(int encryptMode, SecretKey key, String iv, byte[] bytes) throws Exception { + Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); + cipher.init(encryptMode, key, new IvParameterSpec(decodeHex(iv))); + return cipher.doFinal(bytes); + } + + private static SecretKey generateKey(String passPhrase) throws Exception { + SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1"); + + // generate key with salt + PBEKeySpec keySpec = new PBEKeySpec(passPhrase.toCharArray(), SALT, 3000, 256); + SecretKey key = new SecretKeySpec(factory.generateSecret(keySpec).getEncoded(), "AES"); + + return key; + } + + private static SecretKey generateKey(String passPhrase, String salt) throws Exception { + SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1"); + + // generate custom salt + PBEKeySpec saltSpec = new PBEKeySpec(salt.toCharArray(), SALT, 3000, 128); + SecretKey saltKey = new SecretKeySpec(factory.generateSecret(saltSpec).getEncoded(), "AES"); + + // generate key with custom salt + PBEKeySpec keySpec = new PBEKeySpec(passPhrase.toCharArray(), saltKey.toString().getBytes(), 3000, 256); + SecretKey key = new SecretKeySpec(factory.generateSecret(keySpec).getEncoded(), "AES"); + + return key; + } + + private static String encodeHex(byte[] bytes) { + return Hex.encodeHexString(bytes); + } + + private static byte[] decodeHex(String str) throws Exception { + return Hex.decodeHex(str.toCharArray()); + } + + private static byte[] decodeBase64(String str) { + byte[] decodeByte = Base64.decodeBase64(str); + return Base64.decodeBase64(decodeByte); + } + } From 6f882dda91f07b6adff64045f63bb8cf4e781a53 Mon Sep 17 00:00:00 2001 From: minjikim Date: Wed, 2 Aug 2023 02:31:30 +0900 Subject: [PATCH 06/13] =?UTF-8?q?[fix]=20=EC=9D=B5=EB=AA=85=EA=B2=8C?= =?UTF-8?q?=EC=8B=9C=ED=8C=90=20=EB=8C=93=EA=B8=80=20=EC=82=AC=EC=9A=A9?= =?UTF-8?q?=EC=9E=90=20=EA=B5=AC=EB=B6=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/kr/co/wingle/community/comment/CommentMapper.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/wingle/src/main/java/kr/co/wingle/community/comment/CommentMapper.java b/wingle/src/main/java/kr/co/wingle/community/comment/CommentMapper.java index e6336eeb..1c774557 100644 --- a/wingle/src/main/java/kr/co/wingle/community/comment/CommentMapper.java +++ b/wingle/src/main/java/kr/co/wingle/community/comment/CommentMapper.java @@ -22,7 +22,8 @@ public CommentResponseDto toResponseDto(Comment comment) { CommentResponseDto.CommentResponseDtoBuilder commentResponseDto = CommentResponseDto.builder(); commentResponseDto.id(comment.getId()); - commentResponseDto.userId(AES256Util.encrypt(processedPersonalInformation.getProcessedMemberId().toString())); + commentResponseDto.userId( + AES256Util.encrypt(comment.getMember().getId().toString(), comment.getArticle().getId().toString())); commentResponseDto.userNickname(processedPersonalInformation.getNickname()); commentResponseDto.userImage(profileService.getProfileByMemberId(comment.getMember().getId()).getImageUrl()); commentResponseDto.userNation(profileService.getProfileByMemberId(comment.getMember().getId()).getNation()); From aa152bfaff5d9c7dda85955e6268595bf5da75d9 Mon Sep 17 00:00:00 2001 From: minjikim Date: Wed, 2 Aug 2023 18:44:04 +0900 Subject: [PATCH 07/13] =?UTF-8?q?[fix]=20=EC=9D=B5=EB=AA=85=EA=B2=8C?= =?UTF-8?q?=EC=8B=9C=ED=8C=90=20=EA=B2=8C=EC=8B=9C=EA=B8=80=20=EC=9E=91?= =?UTF-8?q?=EC=84=B1=EC=9E=90=20=EA=B5=AC=EB=B6=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/kr/co/wingle/community/article/ArticleMapper.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/wingle/src/main/java/kr/co/wingle/community/article/ArticleMapper.java b/wingle/src/main/java/kr/co/wingle/community/article/ArticleMapper.java index 76c2af9f..ed698aa8 100644 --- a/wingle/src/main/java/kr/co/wingle/community/article/ArticleMapper.java +++ b/wingle/src/main/java/kr/co/wingle/community/article/ArticleMapper.java @@ -38,7 +38,8 @@ public ArticleResponseDto toResponseDto(Article article, List images) { articleResponseDto.images(new ArrayList(list)); } articleResponseDto.isMine(processedPersonalInformation.isMine()); - articleResponseDto.userId(AES256Util.encrypt(processedPersonalInformation.getProcessedMemberId().toString())); + articleResponseDto.userId( + AES256Util.encrypt(article.getMember().getId().toString(), article.getId().toString())); articleResponseDto.userImage(profileService.getProfileByMemberId(article.getMember().getId()).getImageUrl()); articleResponseDto.userNation(profileService.getProfileByMemberId(article.getMember().getId()).getNation()); articleResponseDto.userSchoolName(processedPersonalInformation.getSchoolName()); From 8a4462e4ad71a665f0f150a2cddacbab94e1e89f Mon Sep 17 00:00:00 2001 From: LeeJE20 <42895142+LeeJE20@users.noreply.github.com> Date: Wed, 2 Aug 2023 23:36:26 +0900 Subject: [PATCH 08/13] =?UTF-8?q?[chore]=20test=20=EB=B2=84=ED=82=B7=20?= =?UTF-8?q?=EC=9D=B4=EB=A6=84=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/deploy.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index da0e0a39..cb72b9dd 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -22,7 +22,7 @@ on: env: S3_BUCKET_NAME: wingle-ci-bucket - TEST_S3_BUCKET_NAME: wingle-ci-bucket + TEST_S3_BUCKET_NAME: test-wingle-ci-bucket CODE_DEPLOY_APPLICATION_NAME: wingle-codedeploy-app CODE_DEPLOY_DEPLOYMENT_GROUP_NAME: wingle-codedeploy-group From cd1386cf435ac87a298fc2aeef049e17bbf558f2 Mon Sep 17 00:00:00 2001 From: LeeJE20 <42895142+LeeJE20@users.noreply.github.com> Date: Wed, 2 Aug 2023 23:38:27 +0900 Subject: [PATCH 09/13] =?UTF-8?q?[chore]=20test=20=EB=B2=84=ED=82=B7=20?= =?UTF-8?q?=EC=9D=B4=EB=A6=84=20=EC=98=A4=ED=83=80=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/deploy.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index cb72b9dd..54b64099 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -22,7 +22,7 @@ on: env: S3_BUCKET_NAME: wingle-ci-bucket - TEST_S3_BUCKET_NAME: test-wingle-ci-bucket + TEST_S3_BUCKET_NAME: wingle-test-ci-bucket CODE_DEPLOY_APPLICATION_NAME: wingle-codedeploy-app CODE_DEPLOY_DEPLOYMENT_GROUP_NAME: wingle-codedeploy-group From 90c51bc27850e0727892915f6967c7d1d0fd0bee Mon Sep 17 00:00:00 2001 From: LeeJE20 <42895142+LeeJE20@users.noreply.github.com> Date: Sat, 5 Aug 2023 22:33:49 +0900 Subject: [PATCH 10/13] =?UTF-8?q?[chore]=20=EB=B6=84=EA=B8=B0=20=EB=B8=8C?= =?UTF-8?q?=EB=9E=9C=EC=B9=98=20=EC=B2=B4=ED=81=AC=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit contatins λŒ€μ‹  == μ‚¬μš© --- .github/workflows/deploy.yml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 54b64099..ce246fc4 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -50,7 +50,7 @@ jobs: ${{ runner.os }}-gradle- - name: πŸš€ PROD - make main application.yml - if: contains(github.ref, 'main') + if: github.ref == 'refs/heads/main' run: | sudo mkdir -p ./wingle/src/main/resources sudo chmod 777 ./wingle/src/main/resources @@ -59,7 +59,7 @@ jobs: echo "${{ secrets.MAIN_YML }}" > ./application.yml - name: πŸ‘€ TEST - make stage application.yml - if: contains(github.ref, 'test') + if: github.ref == 'refs/heads/test' run: | sudo mkdir -p ./wingle/src/main/resources sudo chmod 777 ./wingle/src/main/resources @@ -123,7 +123,7 @@ jobs: shell: bash - name: πŸš€ PROD - Configure AWS credentials - if: contains(github.ref, 'main') + if: github.ref == 'refs/heads/main' uses: aws-actions/configure-aws-credentials@v1 with: aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} @@ -131,7 +131,7 @@ jobs: aws-region: ${{ secrets.AWS_REGION }} - name: πŸš€ PROD - Upload to AWS S3 - if: contains(github.ref, 'main') + if: github.ref == 'refs/heads/main' run: | cd ./wingle aws deploy push \ @@ -142,7 +142,7 @@ jobs: # S3 버킷에 μžˆλŠ” νŒŒμΌμ„ λŒ€μƒμœΌλ‘œ CodeDeploy μ‹€ν–‰ - name: πŸš€ PROD - Deploy to AWS EC2 from S3 - if: contains(github.ref, 'main') + if: github.ref == 'refs/heads/main' run: | aws deploy create-deployment \ --application-name ${{ env.CODE_DEPLOY_APPLICATION_NAME }} \ @@ -152,7 +152,7 @@ jobs: - name: πŸ‘€ TEST - Configure AWS credentials - if: contains(github.ref, 'test') + if: github.ref == 'refs/heads/test' uses: aws-actions/configure-aws-credentials@v1 with: aws-access-key-id: ${{ secrets.TEST_AWS_ACCESS_KEY_ID }} @@ -160,7 +160,7 @@ jobs: aws-region: ${{ secrets.AWS_REGION }} - name: πŸ‘€ TEST - Upload to AWS S3 - if: contains(github.ref, 'test') + if: github.ref == 'refs/heads/test' run: | cd ./wingle aws deploy push \ @@ -171,7 +171,7 @@ jobs: # S3 버킷에 μžˆλŠ” νŒŒμΌμ„ λŒ€μƒμœΌλ‘œ CodeDeploy μ‹€ν–‰ - name: πŸ‘€ TEST - Deploy to AWS EC2 from S3 - if: contains(github.ref, 'test') + if: github.ref == 'refs/heads/test' run: | aws deploy create-deployment \ --application-name ${{ env.CODE_DEPLOY_APPLICATION_NAME }} \ From 4600d6d6d2cbb5c33a983cb98f248cb785a2c8f9 Mon Sep 17 00:00:00 2001 From: minjikim Date: Mon, 7 Aug 2023 22:57:22 +0900 Subject: [PATCH 11/13] =?UTF-8?q?[feat]=20=EC=BB=A4=EB=AE=A4=EB=8B=88?= =?UTF-8?q?=ED=8B=B0=20=EA=B2=8C=EC=8B=9C=EA=B8=80=20=EC=82=AC=EC=A7=84=20?= =?UTF-8?q?=EC=97=85=EB=A1=9C=EB=93=9C=20=EA=B8=B0=EB=8A=A5=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/kr/co/wingle/common/util/S3Util.java | 9 ++++- .../community/article/ArticleImage.java | 39 +++++++++++++++++++ .../article/ArticleImageRepository.java | 10 +++++ .../community/article/ArticleService.java | 27 ++++++++++--- 4 files changed, 77 insertions(+), 8 deletions(-) create mode 100644 wingle/src/main/java/kr/co/wingle/community/article/ArticleImage.java create mode 100644 wingle/src/main/java/kr/co/wingle/community/article/ArticleImageRepository.java diff --git a/wingle/src/main/java/kr/co/wingle/common/util/S3Util.java b/wingle/src/main/java/kr/co/wingle/common/util/S3Util.java index 9d9658a0..a41eae74 100644 --- a/wingle/src/main/java/kr/co/wingle/common/util/S3Util.java +++ b/wingle/src/main/java/kr/co/wingle/common/util/S3Util.java @@ -66,8 +66,13 @@ public String profileImageUpload(MultipartFile file) { } } - public String articleImageUpload(MultipartFile file) throws IOException { - return upload(file, "article"); + public String articleImageUpload(MultipartFile file) { + try { + return upload(file, "article"); + } catch (IOException e) { + log.warn(e.getMessage()); + throw new InternalServerErrorException(ErrorCode.FILE_UPLOAD_FAIL); + } } public void delete(String url) { diff --git a/wingle/src/main/java/kr/co/wingle/community/article/ArticleImage.java b/wingle/src/main/java/kr/co/wingle/community/article/ArticleImage.java new file mode 100644 index 00000000..3c008c97 --- /dev/null +++ b/wingle/src/main/java/kr/co/wingle/community/article/ArticleImage.java @@ -0,0 +1,39 @@ +package kr.co.wingle.community.article; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.FetchType; +import javax.persistence.ManyToOne; + +import org.springframework.util.Assert; + +import kr.co.wingle.common.entity.BaseEntity; +import lombok.AccessLevel; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Entity +@Getter +@NoArgsConstructor(access = AccessLevel.PROTECTED) +public class ArticleImage extends BaseEntity { + + @ManyToOne(fetch = FetchType.LAZY) + private Article article; + + @Column(nullable = false) + private String imageUrl; + + @Column(nullable = false) + private int orderNumber; + + @Builder + ArticleImage(Article article, String imageUrl, int orderNumber) { + Assert.notNull(article, "article must not be null"); + Assert.notNull(imageUrl, "imageUrl must not be null"); + + this.article = article; + this.imageUrl = imageUrl; + this.orderNumber = orderNumber; + } +} diff --git a/wingle/src/main/java/kr/co/wingle/community/article/ArticleImageRepository.java b/wingle/src/main/java/kr/co/wingle/community/article/ArticleImageRepository.java new file mode 100644 index 00000000..80df07c1 --- /dev/null +++ b/wingle/src/main/java/kr/co/wingle/community/article/ArticleImageRepository.java @@ -0,0 +1,10 @@ +package kr.co.wingle.community.article; + +import java.util.List; + +import org.springframework.data.jpa.repository.JpaRepository; + +public interface ArticleImageRepository extends JpaRepository { + + List getArticleImagesByArticleIdAndIsDeletedOrderByOrderNumber(Long articleId, boolean isDeleted); +} diff --git a/wingle/src/main/java/kr/co/wingle/community/article/ArticleService.java b/wingle/src/main/java/kr/co/wingle/community/article/ArticleService.java index 6d9881f4..6bd557fd 100644 --- a/wingle/src/main/java/kr/co/wingle/community/article/ArticleService.java +++ b/wingle/src/main/java/kr/co/wingle/community/article/ArticleService.java @@ -13,6 +13,7 @@ import kr.co.wingle.common.constants.ErrorCode; import kr.co.wingle.common.exception.ForbiddenException; import kr.co.wingle.common.exception.NotFoundException; +import kr.co.wingle.common.util.S3Util; import kr.co.wingle.community.forum.Forum; import kr.co.wingle.community.forum.ForumCode; import kr.co.wingle.community.forum.ForumService; @@ -25,9 +26,11 @@ @Service public class ArticleService extends WritingService { private final ArticleRepository articleRepository; + private final ArticleImageRepository articleImageRepository; private final ForumService forumService; private final AuthService authService; private final ArticleMapper articleMapper; + private final S3Util s3Util; @Transactional public ArticleResponseDto create(ArticleRequestDto request) { @@ -47,18 +50,28 @@ public ArticleResponseDto create(ArticleRequestDto request) { articleRepository.save(article); + ArrayList imageUrlList = new ArrayList<>(); + for (int i = 0; i < request.getImages().size(); i++) { + String imageUrl = s3Util.articleImageUpload(request.getImages().get(i)); + imageUrlList.add(imageUrl); + articleImageRepository.save(new ArticleImage(article, imageUrl, i + 1)); + } + // TODO: Redis μ΅œμ‹ λͺ©λ‘μ— 등둝 - // TODO: new ArrayList 뢀뢄을 s3μ—μ„œ 받은 이미지 경둜둜 λ³€κ²½ - return articleMapper.toResponseDto(article, new ArrayList()); + return articleMapper.toResponseDto(article, imageUrlList); } @Transactional(readOnly = true) public ArticleResponseDto getOne(Long forumId, Long articleId) { Article article = getArticleById(articleId); isValidForum(article, forumId); - // TODO: new ArrayList 뢀뢄을 s3μ—μ„œ 받은 이미지 경둜둜 λ³€κ²½ - return articleMapper.toResponseDto(article, new ArrayList()); + + List imageUrlList = articleImageRepository.getArticleImagesByArticleIdAndIsDeletedOrderByOrderNumber( + article.getId(), false) + .stream().map(articleImage -> articleImage.getImageUrl()).collect(Collectors.toList()); + + return articleMapper.toResponseDto(article, imageUrlList); } @Transactional(readOnly = true) @@ -71,9 +84,11 @@ public List getList(Long forumId, int page, int size, boolea } else { pages = articleRepository.findByForumIdAndIsDeleted(forumId, false, pageable); } - // TODO: new ArrayList 뢀뢄을 s3μ—μ„œ 받은 이미지 경둜둜 λ³€κ²½ + return pages.stream() - .map(x -> articleMapper.toResponseDto(x, new ArrayList())) + .map(x -> articleMapper.toResponseDto(x, + articleImageRepository.getArticleImagesByArticleIdAndIsDeletedOrderByOrderNumber(x.getId(), false) + .stream().map(articleImage -> articleImage.getImageUrl()).collect(Collectors.toList()))) .collect( Collectors.toList()); } From 2a9bb9bc5edec9f5ff2705a9c036f41a6a4e7baf Mon Sep 17 00:00:00 2001 From: minjikim Date: Mon, 7 Aug 2023 23:45:12 +0900 Subject: [PATCH 12/13] =?UTF-8?q?[add]=20=EA=B2=8C=EC=8B=9C=EA=B8=80=20?= =?UTF-8?q?=EC=82=AD=EC=A0=9C=20=EC=8B=9C=20=EA=B2=8C=EC=8B=9C=EA=B8=80=20?= =?UTF-8?q?=EC=9D=B4=EB=AF=B8=EC=A7=80=EB=8F=84=20=EA=B0=99=EC=9D=B4=20?= =?UTF-8?q?=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/kr/co/wingle/community/article/ArticleService.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/wingle/src/main/java/kr/co/wingle/community/article/ArticleService.java b/wingle/src/main/java/kr/co/wingle/community/article/ArticleService.java index 6bd557fd..3b1c9a59 100644 --- a/wingle/src/main/java/kr/co/wingle/community/article/ArticleService.java +++ b/wingle/src/main/java/kr/co/wingle/community/article/ArticleService.java @@ -99,6 +99,8 @@ public Long delete(Long forumId, Long articleId) { Article article = getArticleById(articleId); if (isValidMember(article, member) && isExist(article) && isValidForum(article, forumId)) { + articleImageRepository.getArticleImagesByArticleIdAndIsDeletedOrderByOrderNumber(articleId, false) + .forEach(articleImage -> articleImage.softDelete()); article.softDelete(); } return article.getId(); From ec17621ada5ca35513dfb8fe02a8072deae6aa5e Mon Sep 17 00:00:00 2001 From: minjikim Date: Tue, 8 Aug 2023 00:20:04 +0900 Subject: [PATCH 13/13] =?UTF-8?q?[feat]=20=EA=B2=8C=EC=8B=9C=EA=B8=80=20?= =?UTF-8?q?=EC=88=98=EC=A0=95=20=EA=B8=B0=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../community/article/ArticleController.java | 8 +++++++ .../article/ArticleEditRequestDto.java | 23 +++++++++++++++++++ .../article/ArticleImageRepository.java | 2 ++ .../community/article/ArticleService.java | 20 ++++++++++++++++ 4 files changed, 53 insertions(+) create mode 100644 wingle/src/main/java/kr/co/wingle/community/article/ArticleEditRequestDto.java diff --git a/wingle/src/main/java/kr/co/wingle/community/article/ArticleController.java b/wingle/src/main/java/kr/co/wingle/community/article/ArticleController.java index 4b254ea2..a56ae88a 100644 --- a/wingle/src/main/java/kr/co/wingle/community/article/ArticleController.java +++ b/wingle/src/main/java/kr/co/wingle/community/article/ArticleController.java @@ -9,6 +9,7 @@ import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; @@ -63,4 +64,11 @@ public ApiResponse delete(@PathVariable String forumId, articleService.delete(StringUtil.StringToLong(forumId), StringUtil.StringToLong(articleId))); } + @PutMapping("/{forumId}/articles/{articleId}") + public ApiResponse editArticle(@PathVariable String forumId, + @PathVariable String articleId, @ModelAttribute @Valid ArticleEditRequestDto articleEditRequestDto) { + return ApiResponse.success(SuccessCode.GET_SUCCESS, + articleService.editArticle(StringUtil.StringToLong(forumId), StringUtil.StringToLong(articleId), + articleEditRequestDto)); + } } diff --git a/wingle/src/main/java/kr/co/wingle/community/article/ArticleEditRequestDto.java b/wingle/src/main/java/kr/co/wingle/community/article/ArticleEditRequestDto.java new file mode 100644 index 00000000..1363cd0c --- /dev/null +++ b/wingle/src/main/java/kr/co/wingle/community/article/ArticleEditRequestDto.java @@ -0,0 +1,23 @@ +package kr.co.wingle.community.article; + +import java.util.List; + +import org.springframework.web.multipart.MultipartFile; + +import kr.co.wingle.common.validator.LengthWithoutCR; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +@AllArgsConstructor +public class ArticleEditRequestDto { + + @LengthWithoutCR(min = 1, max = 3000, message = "λ‚΄μš©μ€ 1자 이상 3000자 μ΄ν•˜λ§Œ κ°€λŠ₯ν•©λ‹ˆλ‹€.") + private String content; + + private List originImages; + private List newImages; + +} diff --git a/wingle/src/main/java/kr/co/wingle/community/article/ArticleImageRepository.java b/wingle/src/main/java/kr/co/wingle/community/article/ArticleImageRepository.java index 80df07c1..2f27be53 100644 --- a/wingle/src/main/java/kr/co/wingle/community/article/ArticleImageRepository.java +++ b/wingle/src/main/java/kr/co/wingle/community/article/ArticleImageRepository.java @@ -7,4 +7,6 @@ public interface ArticleImageRepository extends JpaRepository { List getArticleImagesByArticleIdAndIsDeletedOrderByOrderNumber(Long articleId, boolean isDeleted); + + List findAllByArticleId(Long articleId); } diff --git a/wingle/src/main/java/kr/co/wingle/community/article/ArticleService.java b/wingle/src/main/java/kr/co/wingle/community/article/ArticleService.java index 3b1c9a59..5dc5cda1 100644 --- a/wingle/src/main/java/kr/co/wingle/community/article/ArticleService.java +++ b/wingle/src/main/java/kr/co/wingle/community/article/ArticleService.java @@ -62,6 +62,26 @@ public ArticleResponseDto create(ArticleRequestDto request) { return articleMapper.toResponseDto(article, imageUrlList); } + public ArticleResponseDto editArticle(Long forumId, Long articleId, ArticleEditRequestDto request) { + Article article = getArticleById(articleId); + isValidForum(article, forumId); + + article.setContent(request.getContent()); + + List allByArticle = articleImageRepository.findAllByArticleId(articleId); + articleImageRepository.deleteAll(allByArticle); + + ArrayList imageUrlList = (ArrayList)request.getOriginImages(); + imageUrlList.addAll(request.getNewImages().stream().map(image -> s3Util.articleImageUpload(image)) + .collect(Collectors.toList())); + + for (int i = 0; i < imageUrlList.size(); i++) { + articleImageRepository.save(new ArticleImage(article, imageUrlList.get(i), i + 1)); + } + + return articleMapper.toResponseDto(article, imageUrlList); + } + @Transactional(readOnly = true) public ArticleResponseDto getOne(Long forumId, Long articleId) { Article article = getArticleById(articleId);