From 33fd2a82e36b225d1e5f59783b2e973fa73d4283 Mon Sep 17 00:00:00 2001 From: Park Seyeon Date: Wed, 29 Nov 2023 15:28:01 +0900 Subject: [PATCH 1/5] =?UTF-8?q?fix:=20Base64=EA=B4=80=EB=A0=A8=20=EB=94=94?= =?UTF-8?q?=EC=BD=94=EB=94=A9=20=EC=BD=94=EB=93=9C=20=EB=B3=80=EA=B2=BD=20?= =?UTF-8?q?->=20Base64Url=20(#173)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: Base64관련 디코딩 코드 변경 -> Base64Url * refactor: 쿠폰 스케쥴 업데이트 및 config 수정 * style: 문자열 checkstyle 수정 --- .../auth/JwtAuthenticationService.java | 8 +- src/main/resources/config | 2 +- src/main/resources/static/docs/coupon.html | 2869 +++++++++++++---- src/main/resources/static/docs/index.html | 2 +- .../resources/static/docs/notification.html | 2 +- .../auth/JwtProviderServiceTest.java | 37 +- 6 files changed, 2314 insertions(+), 606 deletions(-) diff --git a/src/main/java/com/moabam/api/application/auth/JwtAuthenticationService.java b/src/main/java/com/moabam/api/application/auth/JwtAuthenticationService.java index f43c4aa3..eaf1d456 100644 --- a/src/main/java/com/moabam/api/application/auth/JwtAuthenticationService.java +++ b/src/main/java/com/moabam/api/application/auth/JwtAuthenticationService.java @@ -1,6 +1,6 @@ package com.moabam.api.application.auth; -import java.util.Base64; +import java.nio.charset.StandardCharsets; import org.json.JSONObject; import org.springframework.stereotype.Service; @@ -13,6 +13,7 @@ import io.jsonwebtoken.ExpiredJwtException; import io.jsonwebtoken.Jwts; +import io.jsonwebtoken.io.Decoders; import lombok.RequiredArgsConstructor; @Service @@ -37,8 +38,9 @@ public boolean isTokenExpire(String token) { public PublicClaim parseClaim(String token) { String claims = token.split("\\.")[1]; - String decodeClaims = new String(Base64.getDecoder().decode(claims)); - JSONObject jsonObject = new JSONObject(decodeClaims); + byte[] claimsBytes = Decoders.BASE64URL.decode(claims); + String decodedClaims = new String(claimsBytes, StandardCharsets.UTF_8); + JSONObject jsonObject = new JSONObject(decodedClaims); return AuthorizationMapper.toPublicClaim(jsonObject); } diff --git a/src/main/resources/config b/src/main/resources/config index 0f4c27e5..6320f486 160000 --- a/src/main/resources/config +++ b/src/main/resources/config @@ -1 +1 @@ -Subproject commit 0f4c27e5bb593650ad4733c98f5c27b54eebc3c2 +Subproject commit 6320f4860f0be17c32492602f152b6d5a2f9f508 diff --git a/src/main/resources/static/docs/coupon.html b/src/main/resources/static/docs/coupon.html index 0b834827..d2b00d0d 100644 --- a/src/main/resources/static/docs/coupon.html +++ b/src/main/resources/static/docs/coupon.html @@ -1,467 +1,2138 @@ - - - - -쿠폰(Coupon) - - + + + + + 쿠폰(Coupon) + +
-
-

쿠폰(Coupon)

-
-
-
-
쿠폰에 대해 생성/삭제/조회/발급/사용 기능을 제공합니다.
-
-
-
-
-

쿠폰 생성

-
-
-
관리자가 쿠폰을 생성합니다.
-
-
-

요청

-
-
+
+

쿠폰(Coupon)

+
+
+
+
쿠폰에 대해 생성/삭제/조회/발급/사용 기능을 제공합니다.
+
+
+
+
+

쿠폰 생성

+
+
+
관리자가 쿠폰을 생성합니다.
+
+
+

요청

+
+
POST /admins/coupons HTTP/1.1
 Content-Type: application/json;charset=UTF-8
-Content-Length: 175
+Content-Length: 183
 Host: localhost:8080
 
 {
@@ -473,66 +2144,66 @@ 

요청

"startAt" : "2023-02-01", "openAt" : "2023-01-01" }
-
-
-

응답

-
-
+
+
+

응답

+
+
HTTP/1.1 201 Created
 Access-Control-Allow-Origin:
 Access-Control-Allow-Methods: GET, HEAD, POST, PUT, DELETE, TRACE, OPTIONS, PATCH
 Access-Control-Allow-Headers: Origin, Accept, Access-Control-Request-Method, Access-Control-Request-Headers, X-Requested-With,Content-Type, Referer
 Access-Control-Allow-Credentials: true
 Access-Control-Max-Age: 3600
-
-
-
-
-
-

쿠폰 삭제

-
-
-
관리자가 쿠폰 ID와 일치하는 쿠폰을 삭제합니다.
-
-
-

요청

-
-
+
+
+
+
+
+

쿠폰 삭제

+
+
+
관리자가 쿠폰 ID와 일치하는 쿠폰을 삭제합니다.
+
+
+

요청

+
+
DELETE /admins/coupons/34 HTTP/1.1
 Host: localhost:8080
-
-
-

응답

-
-
+
+
+

응답

+
+
HTTP/1.1 200 OK
 Access-Control-Allow-Origin:
 Access-Control-Allow-Methods: GET, HEAD, POST, PUT, DELETE, TRACE, OPTIONS, PATCH
 Access-Control-Allow-Headers: Origin, Accept, Access-Control-Request-Method, Access-Control-Request-Headers, X-Requested-With,Content-Type, Referer
 Access-Control-Allow-Credentials: true
 Access-Control-Max-Age: 3600
-
-
-
-
-
-

특정 쿠폰 조회

-
-
-
관리자 혹은 사용자가 특정 ID와 일치하는 쿠폰을 조회합니다.
-
-
-
-

요청

-
-
+
+
+
+
+
+

특정 쿠폰 조회

+
+
+
관리자 혹은 사용자가 특정 ID와 일치하는 쿠폰을 조회합니다.
+
+
+
+

요청

+
+
GET /coupons/22 HTTP/1.1
 Host: localhost:8080
-
-
-

응답

-
-
+
+
+

응답

+
+
HTTP/1.1 200 OK
 Access-Control-Allow-Origin:
 Access-Control-Allow-Methods: GET, HEAD, POST, PUT, DELETE, TRACE, OPTIONS, PATCH
@@ -540,7 +2211,7 @@ 

응답

Access-Control-Allow-Credentials: true Access-Control-Max-Age: 3600 Content-Type: application/json -Content-Length: 198 +Content-Length: 208 { "id" : 22, @@ -553,36 +2224,36 @@

응답

"startAt" : "2023-02-01", "openAt" : "2023-01-01" }
-
-
-
-
-
-
-

상태에 따른 쿠폰들을 조회

-
-
-
관리자 혹은 사용자가 날짜 상태에 따라 쿠폰들을 조회합니다.
-
-
-
-

요청

-
-
+
+
+
+
+
+
+

상태에 따른 쿠폰들을 조회

+
+
+
관리자 혹은 사용자가 날짜 상태에 따라 쿠폰들을 조회합니다.
+
+
+
+

요청

+
+
POST /coupons/search HTTP/1.1
 Content-Type: application/json;charset=UTF-8
-Content-Length: 41
+Content-Length: 44
 Host: localhost:8080
 
 {
   "opened" : false,
   "ended" : false
 }
-
-
-

응답

-
-
+
+
+

응답

+
+
HTTP/1.1 200 OK
 Access-Control-Allow-Origin:
 Access-Control-Allow-Methods: GET, HEAD, POST, PUT, DELETE, TRACE, OPTIONS, PATCH
@@ -590,7 +2261,7 @@ 

응답

Access-Control-Allow-Credentials: true Access-Control-Max-Age: 3600 Content-Type: application/json -Content-Length: 199 +Content-Length: 209 [ { "id" : 23, @@ -603,33 +2274,33 @@

응답

"startAt" : "2023-03-01", "openAt" : "2023-01-01" } ]
-
-
-
-
-
-
-

특정 쿠폰에 대해 발급

-
-
-
사용자가 발급 가능한 쿠폰을 선착순으로 발급 받습니다.
-
-
-
-

요청

-
-
+
+
+
+
+
+
+

특정 쿠폰에 대해 발급

+
+
+
사용자가 발급 가능한 쿠폰을 선착순으로 발급 받습니다.
+
+
+
+

요청

+
+
POST /coupons HTTP/1.1
 Content-Type: application/x-www-form-urlencoded
 Host: localhost:8080
 Content-Length: 21
 
 couponName=couponName
-
-
-

응답

-
-
+
+
+

응답

+
+
HTTP/1.1 400 Bad Request
 Access-Control-Allow-Origin:
 Access-Control-Allow-Methods: GET, HEAD, POST, PUT, DELETE, TRACE, OPTIONS, PATCH
@@ -637,34 +2308,34 @@ 

응답

Access-Control-Allow-Credentials: true Access-Control-Max-Age: 3600 Content-Type: application/json -Content-Length: 64 +Content-Length: 66 { "message" : "쿠폰 발급 가능 기간이 아닙니다." }
-
-
-
-
-
-
-

특정 사용자의 쿠폰 보관함을 조회

-
-
-
사용자가 자신의 보관함에 있는 쿠폰들을 조회합니다.
-
-
-
-

요청

-
-
+
+
+
+
+
+
+

특정 사용자의 쿠폰 보관함을 조회

+
+
+
사용자가 자신의 보관함에 있는 쿠폰들을 조회합니다.
+
+
+
+

요청

+
+
GET /my-coupons HTTP/1.1
 Host: localhost:8080
-
-
-

응답

-
-
+
+
+

응답

+
+
HTTP/1.1 200 OK
 Access-Control-Allow-Origin:
 Access-Control-Allow-Methods: GET, HEAD, POST, PUT, DELETE, TRACE, OPTIONS, PATCH
@@ -672,7 +2343,7 @@ 

응답

Access-Control-Allow-Credentials: true Access-Control-Max-Age: 3600 Content-Type: application/json -Content-Length: 472 +Content-Length: 502 [ { "id" : 17, @@ -705,49 +2376,49 @@

응답

"point" : 10, "type" : "MORNING" } ]
-
-
-
-
-
-
-

쿠폰을 사용

-
-
-
사용자가 자신의 보관함에 있는 쿠폰들을 사용합니다.
-
-
-
-

요청

-
-
+
+
+
+
+
+
+

쿠폰을 사용

+
+
+
사용자가 자신의 보관함에 있는 쿠폰들을 사용합니다.
+
+
+
+

요청

+
+
POST /my-coupons/8 HTTP/1.1
 Host: localhost:8080
 Content-Type: application/x-www-form-urlencoded
-
-
-

응답

-
-
+
+
+

응답

+
+
HTTP/1.1 200 OK
 Access-Control-Allow-Origin:
 Access-Control-Allow-Methods: GET, HEAD, POST, PUT, DELETE, TRACE, OPTIONS, PATCH
 Access-Control-Allow-Headers: Origin, Accept, Access-Control-Request-Method, Access-Control-Request-Headers, X-Requested-With,Content-Type, Referer
 Access-Control-Allow-Credentials: true
 Access-Control-Max-Age: 3600
-
-
-
-
-
-
-
+
+
+
+
+
+
+
- \ No newline at end of file + diff --git a/src/main/resources/static/docs/index.html b/src/main/resources/static/docs/index.html index 62f80fd6..2f33f008 100644 --- a/src/main/resources/static/docs/index.html +++ b/src/main/resources/static/docs/index.html @@ -616,7 +616,7 @@

diff --git a/src/main/resources/static/docs/notification.html b/src/main/resources/static/docs/notification.html index d56f528e..6f789844 100644 --- a/src/main/resources/static/docs/notification.html +++ b/src/main/resources/static/docs/notification.html @@ -513,7 +513,7 @@

응답

diff --git a/src/test/java/com/moabam/api/application/auth/JwtProviderServiceTest.java b/src/test/java/com/moabam/api/application/auth/JwtProviderServiceTest.java index e9190c28..9c985f57 100644 --- a/src/test/java/com/moabam/api/application/auth/JwtProviderServiceTest.java +++ b/src/test/java/com/moabam/api/application/auth/JwtProviderServiceTest.java @@ -9,14 +9,16 @@ import org.json.JSONObject; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; -import com.moabam.api.application.auth.JwtProviderService; import com.moabam.global.auth.model.PublicClaim; import com.moabam.global.config.TokenConfig; import com.moabam.support.fixture.PublicClaimFixture; import io.jsonwebtoken.ExpiredJwtException; import io.jsonwebtoken.Jwts; +import io.jsonwebtoken.io.Decoders; class JwtProviderServiceTest { @@ -56,6 +58,39 @@ void create_access_token_success() throws JSONException { assertThat(iat).isLessThan(exp); } + @DisplayName("토큰 디코딩 실패") + @Test + void decoding_token_failBy_url() { + // given + String token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9" + + ".eyJpc3MiOiJtb2Ftb2Ftb2FiYW0iLCJpYXQiOjE3MDEyMzQyNjksImV4c" + + "CI6MTcwMTIzNDU2OSwiaWQiOjIsIm5pY2tuYW1lIjoiXHVEODNEXHVEQzNC6rOw64-M7J20Iiwicm9sZSI6IlVTRVIifQ" + + ".yVcvshWQ6fsQ0OQ-A5kolDo-8QsLVFCD6dIENKWZH-A"; + String[] parts = token.split("\\."); + + // when + then + assertThatThrownBy(() -> Base64.getDecoder().decode(parts[1])).isInstanceOf(IllegalArgumentException.class); + } + + @DisplayName("토큰 디코딩 성공") + @ParameterizedTest + @ValueSource(strings = { + "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9" + + ".eyJpc3MiOiJtb2Ftb2Ftb2FiYW0iLCJpYXQiOjE3MDEyMzQyNjksImV4cCI6MTcwMjQ0Mzg2OX0" + + ".IrcH_LvBKK1HezgY3PVY-0HQlhP6neEuydH6Mhz4Jgo", + "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9" + + ".eyJpc3MiOiJtb2Ftb2Ftb2FiYW0iLCJpYXQiOjE3MDEyMzQyNjksImV4cCI6MTcwMTIzNDU2OSwiaWQiOjIsIm" + + "5pY2tuYW1lIjoiXHVEODNEXHVEQzNC6rOw64-M7J20Iiwicm9sZSI6IlVTRVIifQ" + + ".yVcvshWQ6fsQ0OQ-A5kolDo-8QsLVFCD6dIENKWZH-A" + }) + void decoding_token_success(String token) { + // given + String[] parts = token.split("\\."); + + // When + Then + assertThatNoException().isThrownBy(() -> Decoders.BASE64URL.decode(parts[1])); + } + @DisplayName("refresh 토큰 생성 성공") @Test void create_refresh_token_success() throws JSONException { From 11aca2e2789303ba34e857a35961a50ad8a01e41 Mon Sep 17 00:00:00 2001 From: Dev Uni Date: Wed, 29 Nov 2023 16:12:15 +0900 Subject: [PATCH 2/5] =?UTF-8?q?hotfix:=20sql=20init=20=EB=B0=A9=EC=8B=9D?= =?UTF-8?q?=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/develop-cd.yml | 2 +- docker-compose-dev.yml | 1 + {src/main/resources/sql => mysql/initdb.d}/data.sql | 0 {src/main/resources/sql => mysql/initdb.d}/schema.sql | 0 src/main/resources/config | 2 +- 5 files changed, 3 insertions(+), 2 deletions(-) rename {src/main/resources/sql => mysql/initdb.d}/data.sql (100%) rename {src/main/resources/sql => mysql/initdb.d}/schema.sql (100%) diff --git a/.github/workflows/develop-cd.yml b/.github/workflows/develop-cd.yml index 60bad952..f7216dc6 100644 --- a/.github/workflows/develop-cd.yml +++ b/.github/workflows/develop-cd.yml @@ -53,7 +53,7 @@ jobs: port: 22 username: ${{ secrets.EC2_INSTANCE_USERNAME }} key: ${{ secrets.EC2_INSTANCE_PRIVATE_KEY }} - source: "./.env, ./docker-compose-dev.yml, ./scripts/*, ./nginx/*" + source: "./.env, ./docker-compose-dev.yml, ./scripts/*, ./nginx/*, ./mysql/*" target: "/home/ubuntu/moabam" - name: 파일 세팅 diff --git a/docker-compose-dev.yml b/docker-compose-dev.yml index 4d1e85a0..4ae64366 100644 --- a/docker-compose-dev.yml +++ b/docker-compose-dev.yml @@ -72,3 +72,4 @@ services: - --collation-server=utf8mb4_unicode_ci volumes: - /home/ubuntu/moabam/data/mysql:/var/lib/mysql + - /home/ubuntu/moabam/sql/initdb.d:/docker-entrypoint-initdb.d diff --git a/src/main/resources/sql/data.sql b/mysql/initdb.d/data.sql similarity index 100% rename from src/main/resources/sql/data.sql rename to mysql/initdb.d/data.sql diff --git a/src/main/resources/sql/schema.sql b/mysql/initdb.d/schema.sql similarity index 100% rename from src/main/resources/sql/schema.sql rename to mysql/initdb.d/schema.sql diff --git a/src/main/resources/config b/src/main/resources/config index 6320f486..a13c9f42 160000 --- a/src/main/resources/config +++ b/src/main/resources/config @@ -1 +1 @@ -Subproject commit 6320f4860f0be17c32492602f152b6d5a2f9f508 +Subproject commit a13c9f42f0dad81be5abd9fde50afa3e905e3509 From b19243e26acc7912feb3dfa11369754687742065 Mon Sep 17 00:00:00 2001 From: Dev Uni Date: Wed, 29 Nov 2023 16:29:42 +0900 Subject: [PATCH 3/5] hotfix: docker-compose mysql --- .github/workflows/develop-cd.yml | 2 ++ docker-compose-dev.yml | 3 ++- mysql/initdb.d/{schema.sql => init.sql} | 0 mysql/initdb.d/{data.sql => item-data.sql} | 0 src/main/resources/config | 2 +- 5 files changed, 5 insertions(+), 2 deletions(-) rename mysql/initdb.d/{schema.sql => init.sql} (100%) rename mysql/initdb.d/{data.sql => item-data.sql} (100%) diff --git a/.github/workflows/develop-cd.yml b/.github/workflows/develop-cd.yml index f7216dc6..0542aaab 100644 --- a/.github/workflows/develop-cd.yml +++ b/.github/workflows/develop-cd.yml @@ -69,6 +69,8 @@ jobs: chmod +x ./scripts/deploy-dev.sh chmod +x ./scripts/init-letsencrypt.sh chmod +x ./scripts/init-nginx-converter.sh + chmod +x ./mysql/init.sql + chmod +x ./mysql/item-data.sql - name: Github Actions IP 보안그룹에서 삭제 if: always() diff --git a/docker-compose-dev.yml b/docker-compose-dev.yml index 4ae64366..5d953072 100644 --- a/docker-compose-dev.yml +++ b/docker-compose-dev.yml @@ -70,6 +70,7 @@ services: command: - --character-set-server=utf8mb4 - --collation-server=utf8mb4_unicode_ci + - --skip-character-set-client-handshake volumes: - /home/ubuntu/moabam/data/mysql:/var/lib/mysql - - /home/ubuntu/moabam/sql/initdb.d:/docker-entrypoint-initdb.d + - /home/ubuntu/moabam/mysql/initdb.d:/docker-entrypoint-initdb.d diff --git a/mysql/initdb.d/schema.sql b/mysql/initdb.d/init.sql similarity index 100% rename from mysql/initdb.d/schema.sql rename to mysql/initdb.d/init.sql diff --git a/mysql/initdb.d/data.sql b/mysql/initdb.d/item-data.sql similarity index 100% rename from mysql/initdb.d/data.sql rename to mysql/initdb.d/item-data.sql diff --git a/src/main/resources/config b/src/main/resources/config index a13c9f42..4dbde487 160000 --- a/src/main/resources/config +++ b/src/main/resources/config @@ -1 +1 @@ -Subproject commit a13c9f42f0dad81be5abd9fde50afa3e905e3509 +Subproject commit 4dbde487226312c2a144165aa28c0cc0b1e7a0bf From ed724f04d0eae4377b5b8df6867dca1fb145c8b5 Mon Sep 17 00:00:00 2001 From: Dev Uni Date: Wed, 29 Nov 2023 16:31:35 +0900 Subject: [PATCH 4/5] hotfix: docker-compose mysql --- .github/workflows/develop-cd.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/develop-cd.yml b/.github/workflows/develop-cd.yml index 0542aaab..bca6e32e 100644 --- a/.github/workflows/develop-cd.yml +++ b/.github/workflows/develop-cd.yml @@ -69,8 +69,8 @@ jobs: chmod +x ./scripts/deploy-dev.sh chmod +x ./scripts/init-letsencrypt.sh chmod +x ./scripts/init-nginx-converter.sh - chmod +x ./mysql/init.sql - chmod +x ./mysql/item-data.sql + chmod +x ./mysql/initdb.d/init.sql + chmod +x ./mysql/initdb.d/item-data.sql - name: Github Actions IP 보안그룹에서 삭제 if: always() From bbf397411598ba6b777f96b2a522845c9f55821d Mon Sep 17 00:00:00 2001 From: Youngmyung Kim <83266154+ymkim97@users.noreply.github.com> Date: Wed, 29 Nov 2023 17:13:29 +0900 Subject: [PATCH 5/5] =?UTF-8?q?fix:=20=EB=B0=A9=EC=9E=A5=20=EC=9E=90?= =?UTF-8?q?=EC=8B=A0=EC=97=90=20=EB=8C=80=ED=95=9C=20=EC=B6=94=EB=B0=A9=20?= =?UTF-8?q?=EB=B2=84=EA=B7=B8=20(#177)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: 방장 자신 추방 못하도록 validate 추가 * feature: 방 수정 전 정보 불러오기에 방장 ID 추가 * test: 테스트 코드 작성 * fix: 방 참여 기록 조회 최신순으로 변경 --- .../api/application/room/RoomService.java | 7 +++++++ .../api/application/room/SearchService.java | 2 +- .../application/room/mapper/RoomMapper.java | 3 ++- .../ParticipantSearchRepository.java | 1 + .../api/dto/room/ManageRoomResponse.java | 1 + .../global/error/model/ErrorMessage.java | 1 + .../api/presentation/RoomControllerTest.java | 19 +++++++++++++++++++ 7 files changed, 32 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/moabam/api/application/room/RoomService.java b/src/main/java/com/moabam/api/application/room/RoomService.java index fbd1fc4e..63b2490c 100644 --- a/src/main/java/com/moabam/api/application/room/RoomService.java +++ b/src/main/java/com/moabam/api/application/room/RoomService.java @@ -135,6 +135,7 @@ public void mandateManager(Long managerId, Long roomId, Long memberId) { @Transactional public void deportParticipant(Long managerId, Long roomId, Long memberId) { + validateDeportParticipant(managerId, memberId); Participant managerParticipant = getParticipant(managerId, roomId); Participant memberParticipant = getParticipant(memberId, roomId); validateManagerAuthorization(managerParticipant); @@ -172,6 +173,12 @@ private Participant getParticipant(Long memberId, Long roomId) { .orElseThrow(() -> new NotFoundException(PARTICIPANT_NOT_FOUND)); } + private void validateDeportParticipant(Long managerId, Long memberId) { + if (managerId.equals(memberId)) { + throw new BadRequestException(PARTICIPANT_DEPORT_ERROR); + } + } + private void validateManagerAuthorization(Participant participant) { if (!participant.isManager()) { throw new ForbiddenException(ROOM_MODIFY_UNAUTHORIZED_REQUEST); diff --git a/src/main/java/com/moabam/api/application/room/SearchService.java b/src/main/java/com/moabam/api/application/room/SearchService.java index fafe30d0..5aec7dc1 100644 --- a/src/main/java/com/moabam/api/application/room/SearchService.java +++ b/src/main/java/com/moabam/api/application/room/SearchService.java @@ -147,7 +147,7 @@ public ManageRoomResponse getRoomForModification(Long memberId, Long roomId) { participantResponses.add(ParticipantMapper.toParticipantResponse(member, contributionPoint)); } - return RoomMapper.toManageRoomResponse(room, routineResponses, participantResponses); + return RoomMapper.toManageRoomResponse(room, memberId, routineResponses, participantResponses); } public GetAllRoomsResponse getAllRooms(@Nullable RoomType roomType, @Nullable Long roomId) { diff --git a/src/main/java/com/moabam/api/application/room/mapper/RoomMapper.java b/src/main/java/com/moabam/api/application/room/mapper/RoomMapper.java index f80eec07..8282c0ee 100644 --- a/src/main/java/com/moabam/api/application/room/mapper/RoomMapper.java +++ b/src/main/java/com/moabam/api/application/room/mapper/RoomMapper.java @@ -99,11 +99,12 @@ public static RoomsHistoryResponse toRoomsHistoryResponse(List routines, + public static ManageRoomResponse toManageRoomResponse(Room room, Long managerId, List routines, List participantResponses) { return ManageRoomResponse.builder() .roomId(room.getId()) .title(room.getTitle()) + .managerId(managerId) .announcement(room.getAnnouncement()) .roomType(room.getRoomType()) .certifyTime(room.getCertifyTime()) diff --git a/src/main/java/com/moabam/api/domain/room/repository/ParticipantSearchRepository.java b/src/main/java/com/moabam/api/domain/room/repository/ParticipantSearchRepository.java index c99a6d48..761ea8c3 100644 --- a/src/main/java/com/moabam/api/domain/room/repository/ParticipantSearchRepository.java +++ b/src/main/java/com/moabam/api/domain/room/repository/ParticipantSearchRepository.java @@ -62,6 +62,7 @@ public List findAllParticipantsByMemberId(Long memberId) { .where( participant.memberId.eq(memberId) ) + .orderBy(participant.createdAt.desc()) .fetch(); } diff --git a/src/main/java/com/moabam/api/dto/room/ManageRoomResponse.java b/src/main/java/com/moabam/api/dto/room/ManageRoomResponse.java index 98f495ae..cbf9c261 100644 --- a/src/main/java/com/moabam/api/dto/room/ManageRoomResponse.java +++ b/src/main/java/com/moabam/api/dto/room/ManageRoomResponse.java @@ -10,6 +10,7 @@ public record ManageRoomResponse( Long roomId, String title, + Long managerId, String announcement, RoomType roomType, int certifyTime, diff --git a/src/main/java/com/moabam/global/error/model/ErrorMessage.java b/src/main/java/com/moabam/global/error/model/ErrorMessage.java index 408e5574..907c756b 100644 --- a/src/main/java/com/moabam/global/error/model/ErrorMessage.java +++ b/src/main/java/com/moabam/global/error/model/ErrorMessage.java @@ -29,6 +29,7 @@ public enum ErrorMessage { INVALID_REQUEST_URL("잘못된 URL 요청입니다."), INVALID_CERTIFY_TIME("현재 인증 시간이 아닙니다."), CERTIFICATION_NOT_FOUND("인증 정보가 없습니다."), + PARTICIPANT_DEPORT_ERROR("방장은 자신을 추방할 수 없습니다."), LOGIN_FAILED("로그인에 실패했습니다."), REQUEST_FAILED("네트워크 접근 실패입니다."), diff --git a/src/test/java/com/moabam/api/presentation/RoomControllerTest.java b/src/test/java/com/moabam/api/presentation/RoomControllerTest.java index 265450c4..0577f001 100644 --- a/src/test/java/com/moabam/api/presentation/RoomControllerTest.java +++ b/src/test/java/com/moabam/api/presentation/RoomControllerTest.java @@ -887,6 +887,25 @@ void deport_member_success() throws Exception { assertThat(participantSearchRepository.findOne(member.getId(), room.getId())).isEmpty(); } + @DisplayName("방장 본인 추방 시도 - 예외 처리") + @WithMember(id = 1L) + @Test + void deport_self_fail() throws Exception { + // given + Room room = RoomFixture.room(); + + Participant managerParticipant = RoomFixture.participant(room, member.getId()); + managerParticipant.enableManager(); + + roomRepository.save(room); + participantRepository.save(managerParticipant); + + // expected + mockMvc.perform(delete("/rooms/" + room.getId() + "/members/" + member.getId())) + .andExpect(status().isBadRequest()) + .andDo(print()); + } + @DisplayName("방장 위임 성공") @WithMember(id = 1L) @Test