From 8d242a36dca16bb90395c09b68cbb1d8741afe6e Mon Sep 17 00:00:00 2001 From: Jin409 Date: Wed, 7 Aug 2024 23:37:08 +0900 Subject: [PATCH 01/10] =?UTF-8?q?[FEAT]=20=EB=A6=AC=EA=B7=B8=20=EB=85=BC?= =?UTF-8?q?=EB=A6=AC=20=EC=82=AD=EC=A0=9C=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84=20#189?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../server/auth/config/SecurityConfig.java | 1 + .../league/application/LeagueService.java | 29 +++++++---- .../server/command/league/domain/League.java | 51 +++++++++++-------- .../league/presentation/LeagueController.java | 32 +++++++----- 4 files changed, 71 insertions(+), 42 deletions(-) diff --git a/src/main/java/com/sports/server/auth/config/SecurityConfig.java b/src/main/java/com/sports/server/auth/config/SecurityConfig.java index 6a566bfa..b145babf 100644 --- a/src/main/java/com/sports/server/auth/config/SecurityConfig.java +++ b/src/main/java/com/sports/server/auth/config/SecurityConfig.java @@ -42,6 +42,7 @@ SecurityFilterChain filterChain(HttpSecurity http, MvcRequestMatcher.Builder mvc .requestMatchers(mvc.pattern("/manager/**"), mvc.pattern(HttpMethod.GET, "/members/info"), mvc.pattern(HttpMethod.POST, "/leagues"), + mvc.pattern(HttpMethod.DELETE, "/leagues/{leagueId}"), mvc.pattern(HttpMethod.POST, "/leagues/*/teams"), mvc.pattern(HttpMethod.POST, "/leagues/{leagueId}/teams"), mvc.pattern(HttpMethod.PUT, "/leagues/{leagueId}/teams/{teamId}"), diff --git a/src/main/java/com/sports/server/command/league/application/LeagueService.java b/src/main/java/com/sports/server/command/league/application/LeagueService.java index c65c26b6..a0fad22b 100644 --- a/src/main/java/com/sports/server/command/league/application/LeagueService.java +++ b/src/main/java/com/sports/server/command/league/application/LeagueService.java @@ -1,25 +1,34 @@ package com.sports.server.command.league.application; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - +import com.sports.server.auth.exception.AuthorizationErrorMessages; +import com.sports.server.command.league.domain.League; import com.sports.server.command.league.domain.LeagueRepository; import com.sports.server.command.league.dto.LeagueRequestDto; import com.sports.server.command.member.domain.Member; import com.sports.server.command.organization.domain.Organization; import com.sports.server.common.application.EntityUtils; - +import com.sports.server.common.exception.UnauthorizedException; import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; @Service @Transactional @RequiredArgsConstructor public class LeagueService { - private final EntityUtils entityUtils; - private final LeagueRepository leagueRepository; + private final EntityUtils entityUtils; + private final LeagueRepository leagueRepository; + + public void register(final Member manager, final LeagueRequestDto.Register request) { + Organization organization = entityUtils.getEntity(request.organizationId(), Organization.class); + leagueRepository.save(request.toEntity(manager, organization)); + } - public void register(final Member manager, final LeagueRequestDto.Register request) { - Organization organization = entityUtils.getEntity(request.organizationId(), Organization.class); - leagueRepository.save(request.toEntity(manager, organization)); - } + public void delete(final Member manager, final Long leagueId) { + League league = entityUtils.getEntity(leagueId, League.class); + if (!league.isManagedBy(manager)) { + throw new UnauthorizedException(AuthorizationErrorMessages.PERMISSION_DENIED); + } + league.delete(); + } } diff --git a/src/main/java/com/sports/server/command/league/domain/League.java b/src/main/java/com/sports/server/command/league/domain/League.java index 311ee866..b23c1f37 100644 --- a/src/main/java/com/sports/server/command/league/domain/League.java +++ b/src/main/java/com/sports/server/command/league/domain/League.java @@ -48,25 +48,36 @@ public class League extends BaseEntity { @Column(name = "is_deleted", nullable = false) private boolean isDeleted; - public League( - final Member manager, - final Organization organization, - final String name, - final LocalDateTime startAt, - final LocalDateTime endAt, - final Round maxRound - ) { - this.manager = manager; - this.organization = organization; - this.name = name; - this.startAt = startAt; - this.endAt = endAt; - this.maxRound = maxRound; - this.inProgressRound = maxRound; - this.isDeleted = false; - } + public League( + final Member manager, + final Organization organization, + final String name, + final LocalDateTime startAt, + final LocalDateTime endAt, + final Round maxRound + ) { + this.manager = manager; + this.organization = organization; + this.name = name; + this.startAt = startAt; + this.endAt = endAt; + this.maxRound = maxRound; + this.inProgressRound = maxRound; + this.isDeleted = false; + } - public boolean isManagedBy(Member manager) { - return this.manager.equals(manager); - } + public boolean isManagedBy(Member manager) { + return this.manager.equals(manager); + } + + public void delete() { + if (isDeleted) { + throw new IllegalArgumentException("이미 삭제된 리그입니다."); + } + this.isDeleted = true; + } + + public String manager() { + return manager.getEmail(); + } } diff --git a/src/main/java/com/sports/server/command/league/presentation/LeagueController.java b/src/main/java/com/sports/server/command/league/presentation/LeagueController.java index 47c7551e..49736b29 100644 --- a/src/main/java/com/sports/server/command/league/presentation/LeagueController.java +++ b/src/main/java/com/sports/server/command/league/presentation/LeagueController.java @@ -1,24 +1,32 @@ package com.sports.server.command.league.presentation; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RestController; - import com.sports.server.command.league.application.LeagueService; import com.sports.server.command.league.dto.LeagueRequestDto; import com.sports.server.command.member.domain.Member; - import lombok.RequiredArgsConstructor; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; @RestController @RequiredArgsConstructor +@RequestMapping("/leagues") public class LeagueController { - private final LeagueService leagueService; + private final LeagueService leagueService; + + @PostMapping + public ResponseEntity register(@RequestBody final LeagueRequestDto.Register register, Member member) { + leagueService.register(member, register); + return ResponseEntity.ok().build(); + } - @PostMapping("/leagues") - public ResponseEntity register(@RequestBody final LeagueRequestDto.Register register, Member member) { - leagueService.register(member, register); - return ResponseEntity.ok().build(); - } + @DeleteMapping("/{leagueId}") + public ResponseEntity delete(final Member member, @PathVariable final Long leagueId) { + leagueService.delete(member, leagueId); + return ResponseEntity.ok().build(); + } } From 0c179bb61efce4dbc4acd2b29eaa45187bc5b637 Mon Sep 17 00:00:00 2001 From: Jin409 Date: Wed, 7 Aug 2024 23:37:20 +0900 Subject: [PATCH 02/10] =?UTF-8?q?[TEST]=20=EC=84=9C=EB=B9=84=EC=8A=A4=20?= =?UTF-8?q?=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=B6=94=EA=B0=80=20#189?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../league/application/LeagueServiceTest.java | 58 +++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 src/test/java/com/sports/server/command/league/application/LeagueServiceTest.java diff --git a/src/test/java/com/sports/server/command/league/application/LeagueServiceTest.java b/src/test/java/com/sports/server/command/league/application/LeagueServiceTest.java new file mode 100644 index 00000000..6a6fed49 --- /dev/null +++ b/src/test/java/com/sports/server/command/league/application/LeagueServiceTest.java @@ -0,0 +1,58 @@ +package com.sports.server.command.league.application; + + +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; + +import com.sports.server.auth.exception.AuthorizationErrorMessages; +import com.sports.server.command.league.domain.League; +import com.sports.server.command.member.domain.Member; +import com.sports.server.common.application.EntityUtils; +import com.sports.server.common.exception.UnauthorizedException; +import com.sports.server.support.ServiceTest; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.jdbc.Sql; + +@Sql("/league-fixture.sql") +public class LeagueServiceTest extends ServiceTest { + @Autowired + private LeagueService leagueService; + + @Autowired + private EntityUtils entityUtils; + + @Nested + @DisplayName("리그를 삭제할 떄") + class LeagueDeleteTest { + @Test + void isDeleted가_true가_된다() { + // given + Long leagueId = 1L; + Member manager = entityUtils.getEntity(1L, Member.class); + + // when + leagueService.delete(manager, leagueId); + + // then + League league = entityUtils.getEntity(leagueId, League.class); + assertThat(league.isDeleted()).isEqualTo(true); + } + + @Test + void 권한이_없는_멤버는_리그를_삭제할_수_없다() { + // given + Long leagueId = 1L; + Member manager = entityUtils.getEntity(3L, Member.class); + + // when & then + assertThatThrownBy( + () -> leagueService.delete(manager, leagueId)) + .isInstanceOf(UnauthorizedException.class) + .hasMessage(AuthorizationErrorMessages.PERMISSION_DENIED); + + } + } +} From 1d2ec7c041a42a3c81f6d104ee6f5d52057c0b9a Mon Sep 17 00:00:00 2001 From: Jin409 Date: Wed, 7 Aug 2024 23:37:28 +0900 Subject: [PATCH 03/10] =?UTF-8?q?[TEST]=20=EB=8F=84=EB=A9=94=EC=9D=B8=20?= =?UTF-8?q?=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=B6=94=EA=B0=80=20#189?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../command/league/domain/LeagueTest.java | 123 +++++++++++------- 1 file changed, 78 insertions(+), 45 deletions(-) diff --git a/src/test/java/com/sports/server/command/league/domain/LeagueTest.java b/src/test/java/com/sports/server/command/league/domain/LeagueTest.java index 2482dcd1..a8fa9b2e 100644 --- a/src/test/java/com/sports/server/command/league/domain/LeagueTest.java +++ b/src/test/java/com/sports/server/command/league/domain/LeagueTest.java @@ -1,56 +1,89 @@ package com.sports.server.command.league.domain; -import static com.sports.server.support.fixture.FixtureMonkeyUtils.*; -import static org.assertj.core.api.Assertions.*; +import static com.sports.server.support.fixture.FixtureMonkeyUtils.entityBuilder; +import static com.sports.server.support.fixture.FixtureMonkeyUtils.maxRoundArbitrary; +import static com.sports.server.support.fixture.FixtureMonkeyUtils.nameArbitrary; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import com.sports.server.command.member.domain.Member; +import com.sports.server.command.organization.domain.Organization; import java.time.LocalDateTime; - import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; -import com.sports.server.command.member.domain.Member; -import com.sports.server.command.organization.domain.Organization; - class LeagueTest { - @Nested - @DisplayName("리그 생성 시") - class CreateLeague { - private Member manager; - private Organization organization; - - @BeforeEach - void setUp() { - manager = entityBuilder(Member.class).sample(); - organization = entityBuilder(Organization.class).sample(); - } - - @Test - void isDeleted가_false로_생성된다() throws Exception { - // given - League sut; - - // when - sut = new League(manager, organization, nameArbitrary().sample(), LocalDateTime.now(), - LocalDateTime.now(), - maxRoundArbitrary().sample()); - - // then - assertThat(sut.isDeleted()).isEqualTo(false); - } - - @Test - void 리그의_현재_라운드와_총_라운드는_같다() throws Exception { - // given - League sut; - - // when - sut = new League(manager, organization, nameArbitrary().sample(), LocalDateTime.now(), LocalDateTime.now(), - maxRoundArbitrary().sample()); - - // then - assertThat(sut.getMaxRound()).isEqualTo(sut.getInProgressRound()); - } - } + @Nested + @DisplayName("리그 생성 시") + class CreateLeague { + private Member manager; + private Organization organization; + + @BeforeEach + void setUp() { + manager = entityBuilder(Member.class).sample(); + organization = entityBuilder(Organization.class).sample(); + } + + @Test + void isDeleted가_false로_생성된다() throws Exception { + // given + League sut; + + // when + sut = new League(manager, organization, nameArbitrary().sample(), LocalDateTime.now(), + LocalDateTime.now(), + maxRoundArbitrary().sample()); + + // then + assertThat(sut.isDeleted()).isEqualTo(false); + } + + @Test + void 리그의_현재_라운드와_총_라운드는_같다() throws Exception { + // given + League sut; + + // when + sut = new League(manager, organization, nameArbitrary().sample(), LocalDateTime.now(), LocalDateTime.now(), + maxRoundArbitrary().sample()); + + // then + assertThat(sut.getMaxRound()).isEqualTo(sut.getInProgressRound()); + } + } + + @Nested + @DisplayName("리그 삭제 시") + class DeleteLeague { + private Member manager; + private Organization organization; + + @BeforeEach + void setUp() { + manager = entityBuilder(Member.class).sample(); + organization = entityBuilder(Organization.class).sample(); + } + + @Test + void 이미_삭제된_리그는_다시_삭제할_수_없다() { + // given + League sut; + + // when + sut = new League(manager, organization, nameArbitrary().sample(), LocalDateTime.now(), LocalDateTime.now(), + maxRoundArbitrary().sample()); + + // 이미 삭제 처리 + sut.delete(); + + // then + assertThatThrownBy( + () -> sut.delete()) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("이미 삭제된 리그입니다."); + } + } } From 1b8b006294f4b03ea12f4e16c972e5ea6146528f Mon Sep 17 00:00:00 2001 From: Jin409 Date: Wed, 7 Aug 2024 23:37:40 +0900 Subject: [PATCH 04/10] =?UTF-8?q?[TEST]=20=EC=9D=B8=EC=88=98=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20=EC=B6=94=EA=B0=80=20#189?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../acceptance/LeagueAcceptanceTest.java | 75 ++++++++++++------- 1 file changed, 46 insertions(+), 29 deletions(-) diff --git a/src/test/java/com/sports/server/command/league/acceptance/LeagueAcceptanceTest.java b/src/test/java/com/sports/server/command/league/acceptance/LeagueAcceptanceTest.java index 8ad5c953..91ff86ac 100644 --- a/src/test/java/com/sports/server/command/league/acceptance/LeagueAcceptanceTest.java +++ b/src/test/java/com/sports/server/command/league/acceptance/LeagueAcceptanceTest.java @@ -1,41 +1,58 @@ package com.sports.server.command.league.acceptance; -import static org.assertj.core.api.Assertions.*; - -import java.time.LocalDateTime; - -import org.junit.jupiter.api.Test; -import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; -import org.springframework.test.context.jdbc.Sql; +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; import com.sports.server.command.league.dto.LeagueRequestDto; import com.sports.server.support.AcceptanceTest; - import io.restassured.RestAssured; import io.restassured.response.ExtractableResponse; import io.restassured.response.Response; +import java.time.LocalDateTime; +import org.junit.jupiter.api.Test; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.test.context.jdbc.Sql; @Sql("/league-fixture.sql") public class LeagueAcceptanceTest extends AcceptanceTest { - @Test - void 대회를_저장한다() throws Exception { - // given - LeagueRequestDto.Register request = new LeagueRequestDto.Register(1L, "우물정 제기차기 대회", "4강", LocalDateTime.now(), - LocalDateTime.now()); - - configureMockJwtForEmail("john.doe@example.com"); - - // when - ExtractableResponse response = RestAssured.given().log().all() - .cookie(COOKIE_NAME, mockToken) - .contentType(MediaType.APPLICATION_JSON_VALUE) - .body(request) - .post("/leagues") - .then().log().all() - .extract(); - - // then - assertThat(response.statusCode()).isEqualTo(HttpStatus.OK.value()); - } + @Test + void 대회를_저장한다() { + // given + LeagueRequestDto.Register request = new LeagueRequestDto.Register(1L, "우물정 제기차기 대회", "4강", LocalDateTime.now(), + LocalDateTime.now()); + + configureMockJwtForEmail("john.doe@example.com"); + + // when + ExtractableResponse response = RestAssured.given().log().all() + .cookie(COOKIE_NAME, mockToken) + .contentType(MediaType.APPLICATION_JSON_VALUE) + .body(request) + .post("/leagues") + .then().log().all() + .extract(); + + // then + assertThat(response.statusCode()).isEqualTo(HttpStatus.OK.value()); + } + + @Test + void 리그를_삭제한다() { + // given + Long leagueId = 1L; + + configureMockJwtForEmail("john.doe@example.com"); + + // when + ExtractableResponse response = RestAssured.given().log().all() + .cookie(COOKIE_NAME, mockToken) + .pathParam("leagueId", leagueId) + .contentType(MediaType.APPLICATION_JSON_VALUE) + .delete("/leagues/{leagueId}") + .then().log().all() + .extract(); + + // then + assertThat(response.statusCode()).isEqualTo(HttpStatus.OK.value()); + } } From 81df8195e6388ca136bead65ebe8dc36937f6a05 Mon Sep 17 00:00:00 2001 From: Jin409 Date: Thu, 8 Aug 2024 00:00:34 +0900 Subject: [PATCH 05/10] =?UTF-8?q?[TEST]=20=EC=84=9C=EB=B9=84=EC=8A=A4=20?= =?UTF-8?q?=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=88=98=EC=A0=95=20#189?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../command/league/application/LeagueServiceTest.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/test/java/com/sports/server/command/league/application/LeagueServiceTest.java b/src/test/java/com/sports/server/command/league/application/LeagueServiceTest.java index 6a6fed49..25e2e3a0 100644 --- a/src/test/java/com/sports/server/command/league/application/LeagueServiceTest.java +++ b/src/test/java/com/sports/server/command/league/application/LeagueServiceTest.java @@ -2,12 +2,12 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static org.assertj.core.api.AssertionsForClassTypes.assertThat; import com.sports.server.auth.exception.AuthorizationErrorMessages; import com.sports.server.command.league.domain.League; import com.sports.server.command.member.domain.Member; import com.sports.server.common.application.EntityUtils; +import com.sports.server.common.exception.NotFoundException; import com.sports.server.common.exception.UnauthorizedException; import com.sports.server.support.ServiceTest; import org.junit.jupiter.api.DisplayName; @@ -28,7 +28,7 @@ public class LeagueServiceTest extends ServiceTest { @DisplayName("리그를 삭제할 떄") class LeagueDeleteTest { @Test - void isDeleted가_true가_된다() { + void 삭제한_이후에는_해당_객체를_찾을_수_없다() { // given Long leagueId = 1L; Member manager = entityUtils.getEntity(1L, Member.class); @@ -37,8 +37,9 @@ class LeagueDeleteTest { leagueService.delete(manager, leagueId); // then - League league = entityUtils.getEntity(leagueId, League.class); - assertThat(league.isDeleted()).isEqualTo(true); + assertThatThrownBy( + () -> entityUtils.getEntity(leagueId, League.class)) + .isInstanceOf(NotFoundException.class); } @Test From 7571fdf0364838c6268d93bbec862264b4d853b0 Mon Sep 17 00:00:00 2001 From: Jin409 Date: Thu, 8 Aug 2024 00:01:43 +0900 Subject: [PATCH 06/10] =?UTF-8?q?[DOCS]=20=EB=A6=AC=EA=B7=B8=20=EC=82=AD?= =?UTF-8?q?=EC=A0=9C=20=EB=AC=B8=EC=84=9C=ED=99=94=20#189?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/docs/asciidoc/api.adoc | 7 + src/main/resources/static/docs/api.html | 122 +++++++++++++----- .../presentation/LeagueControllerTest.java | 111 ++++++++++------ 3 files changed, 167 insertions(+), 73 deletions(-) diff --git a/src/docs/asciidoc/api.adoc b/src/docs/asciidoc/api.adoc index 9c54972f..39a9849d 100644 --- a/src/docs/asciidoc/api.adoc +++ b/src/docs/asciidoc/api.adoc @@ -94,12 +94,18 @@ operation::league-team-controller-test/리그팀을_삭제한다[snippets='http- operation::league-query-controller-test/리그를_하나_조회한다[snippets='http-request,path-parameters,http-response,response-fields'] +=== 리그 삭제 + +operation::league-controller-test/리그를_삭제한다[snippets='http-request,path-parameters,http-response'] + == 타임라인 API === 득점 타임라인 생성 + operation::timeline-controller-test/득점_타임라인을_생성한다[snippets='http-request,path-parameters,http-response'] === 교체 타임라인 생성 + operation::timeline-controller-test/교체_타임라인을_생성한다[snippets='http-request,path-parameters,http-response'] === 게임의 타임라인 조회 @@ -107,6 +113,7 @@ operation::timeline-controller-test/교체_타임라인을_생성한다[snippets operation::timeline-query-controller-test/타임라인을_조회한다[snippets='http-request,path-parameters,http-response,response-fields'] === 타임라인 삭제 + operation::timeline-controller-test/타임라인을_삭제한다[snippets='http-request,request-cookies,path-parameters,http-response'] == 스포츠 API diff --git a/src/main/resources/static/docs/api.html b/src/main/resources/static/docs/api.html index c63f0fc3..e61c283c 100644 --- a/src/main/resources/static/docs/api.html +++ b/src/main/resources/static/docs/api.html @@ -488,6 +488,7 @@

훕치치 서버 API 문서

  • 리그팀 수정
  • 리그팀 삭제
  • 리그 상세 조회
  • +
  • 리그 삭제
  • 타임라인 API @@ -495,6 +496,7 @@

    훕치치 서버 API 문서

  • 득점 타임라인 생성
  • 교체 타임라인 생성
  • 게임의 타임라인 조회
  • +
  • 타임라인 삭제
  • 스포츠 API @@ -1591,8 +1593,8 @@

    @@ -1939,28 +1941,6 @@

    -

    Path parameters

    - - ---- - - - - - - - - - - - - -
    Table 1. /leagues/{leagueId}/teams
    ParameterDescription

    leagueId

    리그의 ID

    - -

    Request fields

    @@ -2318,6 +2298,53 @@

    +

    리그 삭제

    +
    +

    HTTP request

    +
    +
    +
    DELETE /leagues/1 HTTP/1.1
    +Content-Type: application/json
    +Host: www.api.hufstreaming.site
    +Cookie: HCC_SES=temp-cookie
    +
    +
    +
    +

    + ++++ + + + + + + + + + + + + +
    Table 1. /leagues/{leagueId}
    ParameterDescription

    leagueId

    삭제할 리그의 ID

    +
    +
    +

    HTTP response

    +
    +
    +
    HTTP/1.1 200 OK
    +Vary: Origin
    +Vary: Access-Control-Request-Method
    +Vary: Access-Control-Request-Headers
    +
    +
    +
    +
    @@ -2338,8 +2365,8 @@

    @@ -2373,7 +2400,8 @@

    HTTP/1.1 201 Created Vary: Origin Vary: Access-Control-Request-Method -Vary: Access-Control-Request-Headers +Vary: Access-Control-Request-Headers +Location: @@ -2393,9 +2421,9 @@

    @@ -2429,7 +2457,8 @@

    HTTP/1.1 201 Created Vary: Origin Vary: Access-Control-Request-Method -Vary: Access-Control-Request-Headers +Vary: Access-Control-Request-Headers +Location: @@ -2830,7 +2859,7 @@

    +

    Response fields

    + +++++ + + + + + + + + + + + + + + + + + + + +
    PathTypeDescription

    [].id

    Number

    스포츠의 ID

    [].name

    String

    스포츠의 이름

    + @@ -2875,7 +2933,7 @@

    diff --git a/src/test/java/com/sports/server/command/league/presentation/LeagueControllerTest.java b/src/test/java/com/sports/server/command/league/presentation/LeagueControllerTest.java index 695636e1..f90ed589 100644 --- a/src/test/java/com/sports/server/command/league/presentation/LeagueControllerTest.java +++ b/src/test/java/com/sports/server/command/league/presentation/LeagueControllerTest.java @@ -1,54 +1,83 @@ package com.sports.server.command.league.presentation; -import static org.mockito.Mockito.*; -import static org.springframework.restdocs.cookies.CookieDocumentation.*; -import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.*; -import static org.springframework.restdocs.payload.PayloadDocumentation.*; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; +import static org.mockito.Mockito.any; +import static org.mockito.Mockito.doNothing; +import static org.springframework.restdocs.cookies.CookieDocumentation.cookieWithName; +import static org.springframework.restdocs.cookies.CookieDocumentation.requestCookies; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.delete; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.post; +import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath; +import static org.springframework.restdocs.payload.PayloadDocumentation.requestFields; +import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName; +import static org.springframework.restdocs.request.RequestDocumentation.pathParameters; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; +import com.sports.server.command.league.dto.LeagueRequestDto; +import com.sports.server.command.member.domain.Member; +import com.sports.server.support.DocumentationTest; +import jakarta.servlet.http.Cookie; import java.time.LocalDateTime; - import org.junit.jupiter.api.Test; import org.springframework.http.MediaType; import org.springframework.restdocs.payload.JsonFieldType; import org.springframework.test.web.servlet.ResultActions; -import com.sports.server.command.league.dto.LeagueRequestDto; -import com.sports.server.command.member.domain.Member; -import com.sports.server.support.DocumentationTest; +class LeagueControllerTest extends DocumentationTest { -import jakarta.servlet.http.Cookie; + @Test + void 리그를_생성한다() throws Exception { + // given + LeagueRequestDto.Register request = new LeagueRequestDto.Register(1L, "우물정 제기차기 대회", "4강", LocalDateTime.now(), + LocalDateTime.now()); + Cookie cookie = new Cookie(COOKIE_NAME, "temp-cookie"); -class LeagueControllerTest extends DocumentationTest { + doNothing().when(leagueService).register(any(Member.class), any(LeagueRequestDto.Register.class)); + + // when + ResultActions result = mockMvc.perform(post("/leagues", request) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(request)) + .cookie(cookie)); + + // then + result.andExpect(status().isOk()) + .andDo(restDocsHandler.document( + requestFields( + fieldWithPath("organizationId").type(JsonFieldType.NUMBER).description("조직 id"), + fieldWithPath("name").type(JsonFieldType.STRING).description("대회 이름"), + fieldWithPath("maxRound").type(JsonFieldType.STRING).description("대회 진행 라운드 수"), + fieldWithPath("startAt").type(JsonFieldType.STRING).description("대회 시작 시간"), + fieldWithPath("endAt").type(JsonFieldType.STRING).description("대회 종료 시간") + ), + requestCookies( + cookieWithName(COOKIE_NAME).description("로그인을 통해 얻은 토큰") + ) + ) + ); + } + + @Test + void 리그를_삭제한다() throws Exception { + // given + Cookie cookie = new Cookie(COOKIE_NAME, "temp-cookie"); + + doNothing().when(leagueService).delete(any(Member.class), any()); + + // when + ResultActions result = mockMvc.perform(delete("/leagues/{leagueId}", 1L) + .contentType(MediaType.APPLICATION_JSON) + .cookie(cookie) + ); - @Test - void 리그를_생성한다() throws Exception { - // given - LeagueRequestDto.Register request = new LeagueRequestDto.Register(1L, "우물정 제기차기 대회", "4강", LocalDateTime.now(), LocalDateTime.now()); - Cookie cookie = new Cookie(COOKIE_NAME, "temp-cookie"); - - doNothing().when(leagueService).register(any(Member.class), any(LeagueRequestDto.Register.class)); - - // when - ResultActions result = mockMvc.perform(post("/leagues", request) - .contentType(MediaType.APPLICATION_JSON) - .content(objectMapper.writeValueAsString(request)) - .cookie(cookie)); - - // then - result.andExpect(status().isOk()) - .andDo(restDocsHandler.document( - requestFields( - fieldWithPath("organizationId").type(JsonFieldType.NUMBER).description("조직 id"), - fieldWithPath("name").type(JsonFieldType.STRING).description("대회 이름"), - fieldWithPath("maxRound").type(JsonFieldType.STRING).description("대회 진행 라운드 수"), - fieldWithPath("startAt").type(JsonFieldType.STRING).description("대회 시작 시간"), - fieldWithPath("endAt").type(JsonFieldType.STRING).description("대회 종료 시간") - ), - requestCookies( - cookieWithName(COOKIE_NAME).description("로그인을 통해 얻은 토큰") - ) - ) - ); - } + // then + result.andExpect(status().isOk()) + .andDo(restDocsHandler.document( + pathParameters( + parameterWithName("leagueId").description("삭제할 리그의 ID")), + requestCookies( + cookieWithName(COOKIE_NAME).description("로그인을 통해 얻은 토큰") + ) + ) + ); + } } \ No newline at end of file From 1329e5cb01dda1d02b6f8bcf033dd72f25c4ab52 Mon Sep 17 00:00:00 2001 From: Jin409 Date: Sat, 10 Aug 2024 14:39:04 +0900 Subject: [PATCH 07/10] =?UTF-8?q?[REFACTOR]=20=EB=A9=B1=EB=93=B1=EC=84=B1?= =?UTF-8?q?=EC=9D=84=20=EC=9C=84=ED=95=B4=20=EC=98=88=EC=99=B8=EB=A5=BC=20?= =?UTF-8?q?=EB=8D=98=EC=A7=80=EC=A7=80=20=EC=95=8A=EB=8F=84=EB=A1=9D=20?= =?UTF-8?q?=EC=88=98=EC=A0=95=20#189?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/sports/server/command/league/domain/League.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/main/java/com/sports/server/command/league/domain/League.java b/src/main/java/com/sports/server/command/league/domain/League.java index b23c1f37..8fafe1ef 100644 --- a/src/main/java/com/sports/server/command/league/domain/League.java +++ b/src/main/java/com/sports/server/command/league/domain/League.java @@ -71,9 +71,6 @@ public boolean isManagedBy(Member manager) { } public void delete() { - if (isDeleted) { - throw new IllegalArgumentException("이미 삭제된 리그입니다."); - } this.isDeleted = true; } From ee8bfa70f958a80d9cb7e70c874eb08b276ee846 Mon Sep 17 00:00:00 2001 From: Jin409 Date: Sat, 10 Aug 2024 14:39:18 +0900 Subject: [PATCH 08/10] =?UTF-8?q?[FEAT]=20@SqlDelete=20=EB=A5=BC=20?= =?UTF-8?q?=EC=9D=B4=EC=9A=A9=ED=95=B4=20=EB=85=BC=EB=A6=AC=20=EC=82=AD?= =?UTF-8?q?=EC=A0=9C=EA=B0=80=20=EC=9D=B4=EB=A4=84=EC=A7=80=EB=8F=84?= =?UTF-8?q?=EB=A1=9D=20=EC=88=98=EC=A0=95=20#189?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../server/command/league/application/LeagueService.java | 2 +- .../java/com/sports/server/command/league/domain/League.java | 2 ++ .../sports/server/command/league/domain/LeagueRepository.java | 4 +++- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/sports/server/command/league/application/LeagueService.java b/src/main/java/com/sports/server/command/league/application/LeagueService.java index a0fad22b..15d1142d 100644 --- a/src/main/java/com/sports/server/command/league/application/LeagueService.java +++ b/src/main/java/com/sports/server/command/league/application/LeagueService.java @@ -29,6 +29,6 @@ public void delete(final Member manager, final Long leagueId) { if (!league.isManagedBy(manager)) { throw new UnauthorizedException(AuthorizationErrorMessages.PERMISSION_DENIED); } - league.delete(); + leagueRepository.delete(league); } } diff --git a/src/main/java/com/sports/server/command/league/domain/League.java b/src/main/java/com/sports/server/command/league/domain/League.java index 8fafe1ef..5ddfb63d 100644 --- a/src/main/java/com/sports/server/command/league/domain/League.java +++ b/src/main/java/com/sports/server/command/league/domain/League.java @@ -13,11 +13,13 @@ import lombok.AccessLevel; import lombok.Getter; import lombok.NoArgsConstructor; +import org.hibernate.annotations.SQLDelete; import org.hibernate.annotations.Where; @Entity @Table(name = "leagues") @Where(clause = "is_deleted = 0") +@SQLDelete(sql = "UPDATE leagues SET is_deleted = 1 WHERE league_id = ?") @NoArgsConstructor(access = AccessLevel.PROTECTED) @Getter public class League extends BaseEntity { diff --git a/src/main/java/com/sports/server/command/league/domain/LeagueRepository.java b/src/main/java/com/sports/server/command/league/domain/LeagueRepository.java index 692edde2..cf0e858f 100644 --- a/src/main/java/com/sports/server/command/league/domain/LeagueRepository.java +++ b/src/main/java/com/sports/server/command/league/domain/LeagueRepository.java @@ -3,5 +3,7 @@ import org.springframework.data.repository.Repository; public interface LeagueRepository extends Repository { - void save(League league); + void save(League league); + + void delete(League league); } From edd5ff9f791d163bb6c823081ec9e0f428057433 Mon Sep 17 00:00:00 2001 From: Jin409 Date: Mon, 12 Aug 2024 15:35:23 +0900 Subject: [PATCH 09/10] =?UTF-8?q?[FIX]=20@SqlDelete=20=EB=AC=B8=20?= =?UTF-8?q?=EC=88=98=EC=A0=95=20#189?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/sports/server/command/league/domain/League.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/sports/server/command/league/domain/League.java b/src/main/java/com/sports/server/command/league/domain/League.java index 5ddfb63d..96a80bde 100644 --- a/src/main/java/com/sports/server/command/league/domain/League.java +++ b/src/main/java/com/sports/server/command/league/domain/League.java @@ -19,7 +19,7 @@ @Entity @Table(name = "leagues") @Where(clause = "is_deleted = 0") -@SQLDelete(sql = "UPDATE leagues SET is_deleted = 1 WHERE league_id = ?") +@SQLDelete(sql = "UPDATE leagues SET is_deleted = 1 WHERE id = ?") @NoArgsConstructor(access = AccessLevel.PROTECTED) @Getter public class League extends BaseEntity { From 675790f7753e297990f09fb6f05a9d05ff139009 Mon Sep 17 00:00:00 2001 From: Jin409 Date: Mon, 12 Aug 2024 15:36:00 +0900 Subject: [PATCH 10/10] =?UTF-8?q?[TEST]=20=EC=BD=94=EB=93=9C=20=EC=88=98?= =?UTF-8?q?=EC=A0=95=EC=97=90=20=EB=94=B0=EB=A5=B8=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20=EC=88=98=EC=A0=95=20#189?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../command/league/domain/LeagueTest.java | 24 ++----------------- 1 file changed, 2 insertions(+), 22 deletions(-) diff --git a/src/test/java/com/sports/server/command/league/domain/LeagueTest.java b/src/test/java/com/sports/server/command/league/domain/LeagueTest.java index a8fa9b2e..20f7dc0e 100644 --- a/src/test/java/com/sports/server/command/league/domain/LeagueTest.java +++ b/src/test/java/com/sports/server/command/league/domain/LeagueTest.java @@ -4,7 +4,6 @@ import static com.sports.server.support.fixture.FixtureMonkeyUtils.maxRoundArbitrary; import static com.sports.server.support.fixture.FixtureMonkeyUtils.nameArbitrary; import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatThrownBy; import com.sports.server.command.member.domain.Member; import com.sports.server.command.organization.domain.Organization; @@ -28,7 +27,7 @@ void setUp() { } @Test - void isDeleted가_false로_생성된다() throws Exception { + void isDeleted가_false로_생성된다() { // given League sut; @@ -42,7 +41,7 @@ void setUp() { } @Test - void 리그의_현재_라운드와_총_라운드는_같다() throws Exception { + void 리그의_현재_라운드와_총_라운드는_같다() { // given League sut; @@ -66,24 +65,5 @@ void setUp() { manager = entityBuilder(Member.class).sample(); organization = entityBuilder(Organization.class).sample(); } - - @Test - void 이미_삭제된_리그는_다시_삭제할_수_없다() { - // given - League sut; - - // when - sut = new League(manager, organization, nameArbitrary().sample(), LocalDateTime.now(), LocalDateTime.now(), - maxRoundArbitrary().sample()); - - // 이미 삭제 처리 - sut.delete(); - - // then - assertThatThrownBy( - () -> sut.delete()) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("이미 삭제된 리그입니다."); - } } }