Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
bcc18d2
add show_list_inquiry.md for show listing API documentation
YeaChan05 Sep 17, 2025
5ae9a2b
add integration test for GET /api/show endpoint and update documentation
YeaChan05 Sep 17, 2025
e687292
update DocsUtils and IntegrationTestUtils to support variable path pa…
YeaChan05 Sep 17, 2025
5b38e4d
add inquire endpoint to ShowController for show inquiries
YeaChan05 Sep 17, 2025
9738e26
implement authorization request matchers for API endpoints
YeaChan05 Sep 17, 2025
b0606ed
add assertion to verify unauthorized status in GET /api/show integrat…
YeaChan05 Sep 17, 2025
b6d89e4
add test for handling invalid or expired tokens in GET /api/show
YeaChan05 Sep 17, 2025
ace025b
update content references to contents in show list inquiry documentation
YeaChan05 Sep 17, 2025
bba31a0
add inquire endpoint and response structure for show inquiries
YeaChan05 Sep 17, 2025
b255465
add test to verify empty contents and hasNext=false when no shows exist
YeaChan05 Sep 19, 2025
aeb2d91
implement show fetching functionality and add utility classes for enu…
YeaChan05 Sep 19, 2025
7041301
add tests for pagination and size limits in show inquiries
YeaChan05 Sep 19, 2025
b09f946
update show response handling and utility methods in tests
YeaChan05 Sep 19, 2025
f8ef708
refactor integration tests to use TestFixture for dummy data creation
YeaChan05 Sep 19, 2025
88095d5
update show inquiry handling to enforce request parameter constraints…
YeaChan05 Sep 19, 2025
3a419c3
update show inquiry endpoint to enforce minimum size constraint and a…
YeaChan05 Sep 19, 2025
dee8feb
update show inquiry to enforce enum constraints on type and rating pa…
YeaChan05 Sep 20, 2025
23311b6
update show inquiry to support nullable enum parameters and enhance t…
YeaChan05 Sep 20, 2025
9a05eb3
update show inquiry tests to filter results by query parameter and en…
YeaChan05 Sep 20, 2025
e0301b3
update show inquiry to sort results by performanceStartDate DESC and …
YeaChan05 Sep 20, 2025
129996f
update show inquiry to filter shows by date range, enhance test cover…
YeaChan05 Sep 20, 2025
d197ef2
update show inquiry tests to verify filtering by 'from' parameter, en…
YeaChan05 Sep 20, 2025
301b897
update show inquiry tests to verify filtering by 'to' parameter, enha…
YeaChan05 Sep 20, 2025
1f21409
update show inquiry tests to verify empty contents for non-overlappin…
YeaChan05 Sep 20, 2025
e77c02b
update show inquiry to return BAD_REQUEST for invalid from or to date…
YeaChan05 Sep 20, 2025
d40bbf8
update show inquiry to return BAD_REQUEST for from date after to date…
YeaChan05 Sep 20, 2025
3560656
update show inquiry documentation to clarify test cases and expected …
YeaChan05 Sep 20, 2025
efbf707
update show inquiry to return BAD_REQUEST for empty 'q' parameter, en…
YeaChan05 Sep 21, 2025
b82f15e
update show inquiry to handle empty 'q' parameter and validate date r…
YeaChan05 Sep 21, 2025
8242731
update show inquiry to set default pagination values, enhance hasNext…
YeaChan05 Sep 21, 2025
b09a608
update EnumRequestValidator to improve validation logic and add tests…
YeaChan05 Sep 21, 2025
75dc7e9
refactor SecurityConfig to remove unused AuthorizationRequestMatcherC…
YeaChan05 Sep 21, 2025
fe46f32
update show inquiry documentation to reflect hasNext logic for non-la…
YeaChan05 Sep 21, 2025
ae4be25
update show inquiry tests to verify hallName retrieval and enhance do…
YeaChan05 Sep 21, 2025
81c2528
update show registration to include hallId in requests and improve re…
YeaChan05 Sep 21, 2025
6d56a45
remove hallId from show schedule registration requests and update rel…
YeaChan05 Sep 21, 2025
e25815d
add test for handling non-existent hallId and update documentation
YeaChan05 Sep 21, 2025
7847e05
refactor show inquiry endpoint to use ShowInquiryRequest for improved…
YeaChan05 Sep 21, 2025
451a47f
enhance ShowInquiryRequest validation and simplify fetchShows method
YeaChan05 Sep 21, 2025
f559836
refactor venue to hall terminology and update related classes and doc…
YeaChan05 Sep 21, 2025
1f9d1f0
refactor show query handling with NullableQueryFilterBuilder for impr…
YeaChan05 Sep 22, 2025
509251a
refactor authentication and member-related classes for improved struc…
YeaChan05 Sep 22, 2025
e9eb2fe
refactor show and show schedule models to update hallId handling and …
YeaChan05 Sep 22, 2025
2289a72
update todo list with hall registration tasks and additional show reg…
YeaChan05 Sep 22, 2025
4af85ad
refactor show query handling to simplify SliceView construction and r…
YeaChan05 Sep 22, 2025
c558875
add initial implementation for performance-sensitive show list retrie…
YeaChan05 Sep 22, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package org.mandarin.booking.adapter.security;

import org.mandarin.booking.adapter.AuthorizationRequestMatcherConfigurer;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configurers.AuthorizeHttpRequestsConfigurer;
import org.springframework.stereotype.Component;

@Component
class ApplicationAuthorizationRequestMatcherConfigurer implements AuthorizationRequestMatcherConfigurer {
@Override
public void authorizeRequests(
AuthorizeHttpRequestsConfigurer<HttpSecurity>.AuthorizationManagerRequestMatcherRegistry auth
) {
auth
.requestMatchers(HttpMethod.POST, "/api/member").permitAll()
.requestMatchers("/api/auth/login").permitAll()
.requestMatchers("/api/auth/reissue").permitAll()
.requestMatchers(HttpMethod.POST, "/api/show/schedule").hasAuthority("ROLE_DISTRIBUTOR")
.requestMatchers(HttpMethod.GET, "/api/show").permitAll()
.requestMatchers(HttpMethod.POST, "/api/show").hasAuthority("ROLE_ADMIN")
.anyRequest().authenticated();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
@NullMarked
package org.mandarin.booking.adapter.security;

import org.jspecify.annotations.NullMarked;
Original file line number Diff line number Diff line change
@@ -1,19 +1,29 @@
package org.mandarin.booking.adapter.webapi;

import jakarta.validation.Valid;
import org.mandarin.booking.adapter.SliceView;
import org.mandarin.booking.app.show.ShowFetcher;
import org.mandarin.booking.app.show.ShowRegisterer;
import org.mandarin.booking.domain.show.ShowInquiryRequest;
import org.mandarin.booking.domain.show.ShowRegisterRequest;
import org.mandarin.booking.domain.show.ShowRegisterResponse;
import org.mandarin.booking.domain.show.ShowResponse;
import org.mandarin.booking.domain.show.ShowScheduleRegisterRequest;
import org.mandarin.booking.domain.show.ShowScheduleRegisterResponse;
import org.springframework.web.bind.annotation.GetMapping;
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
@RequestMapping("/api/show")
record ShowController(ShowRegisterer showRegisterer) {
record ShowController(ShowRegisterer showRegisterer, ShowFetcher showFetcher) {

@GetMapping
SliceView<ShowResponse> inquire(@Valid ShowInquiryRequest req) {
return showFetcher.fetchShows(req.page(), req.size(), req.type(), req.rating(), req.q(), req.from(), req.to());
}

@PostMapping
ShowRegisterResponse register(@RequestBody @Valid ShowRegisterRequest request) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
package org.mandarin.booking.app;

import com.querydsl.core.BooleanBuilder;
import com.querydsl.core.types.Predicate;
import com.querydsl.core.types.dsl.TemporalExpression;
import java.util.function.Function;
import org.jspecify.annotations.Nullable;

/**
* Querydsl BooleanBuilder를 감싸는 유틸리티 빌더 클래스 - 조건을 "값이 존재할 때만" 동적으로 추가할 수 있도록 도와줌 - 가독성을 높이고 null/blank 체크를 내부로 숨겨 호출부를
* 단순하게 만듦
*/
public class NullableQueryFilterBuilder {
private final BooleanBuilder builder = new BooleanBuilder();

private NullableQueryFilterBuilder() {
}

public BooleanBuilder build() {
return builder;
}

/**
* 값이 null이 아닐 경우에만 mapper를 통해 Predicate를 생성 후 and 조건으로 추가 예: when(type, t -> show.type.eq(t))
*/
public <T> NullableQueryFilterBuilder when(@Nullable T value, Function<T, Predicate> mapper) {
if (value != null) {
builder.and(mapper.apply(value));
}
return this;
}

/**
* 문자열이 null이 아니고 공백이 아닐 때만 mapper 적용 예: whenHasText(q, s -> show.title.containsIgnoreCase(s))
*/
public NullableQueryFilterBuilder whenHasText(@Nullable String value, Function<String, Predicate> mapper) {
if (value != null && !value.isBlank()) {
builder.and(mapper.apply(value));
}
return this;
}

/**
* from, to 둘 다 존재할 때만 between 조건을 추가
*
* @param from 요청 구간 시작 (예: LocalDate, LocalDateTime)
* @param to 요청 구간 종료
* @param startExpr 엔티티의 시작 값 경로 (예: show.performanceStartDate)
* @param endExpr 엔티티의 종료 값 경로 (예: show.performanceEndDate)
*/
public <T extends Comparable<? super T>> NullableQueryFilterBuilder whenInPeriod(
@Nullable T from,
@Nullable T to,
TemporalExpression<T> startExpr,
TemporalExpression<T> endExpr
) {
if (from != null) {
builder.and(startExpr.after(from));
}
if (to != null) {
builder.and(endExpr.before(to));
}
return this;
}

public static NullableQueryFilterBuilder builder() {
return new NullableQueryFilterBuilder();
}

// /**
// * 두 값이 모두 존재할 때만 mapper 적용
// * 예: whenBoth(from, to, (f, t) -> show.performanceDate.between(f, t))
// */
// public <L, R> NullableQueryFilterBuilder whenBoth(@Nullable L left, @Nullable R right, BiFunction<L, R, Predicate> mapper) {
// if (left != null && right != null) {
// builder.and(mapper.apply(left, right));
// }
// return this;
// }
//
// /**
// * BooleanExpression을 직접 and 조건으로 추가
// * (이미 조건식이 준비된 경우 사용)
// */
// public NullableQueryFilterBuilder and(@Nullable BooleanExpression expr) {
// if (expr != null) {
// builder.and(expr);
// }
// return this;
// }
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package org.mandarin.booking.app.venue;
package org.mandarin.booking.app.hall;

import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Repository;
Expand All @@ -7,10 +7,10 @@
@Repository
@Transactional(readOnly = true)
@RequiredArgsConstructor
public class HallQueryRepository {
class HallQueryRepository {
private final HallRepository repository;

public boolean existsById(Long hallId) {
boolean existsById(Long hallId) {
return repository.existsById(hallId);
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package org.mandarin.booking.app.venue;
package org.mandarin.booking.app.hall;

import org.mandarin.booking.domain.venue.Hall;
import org.mandarin.booking.domain.hall.Hall;
import org.springframework.data.repository.Repository;

interface HallRepository extends Repository<Hall, Long> {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package org.mandarin.booking.app.venue;
package org.mandarin.booking.app.hall;

import lombok.RequiredArgsConstructor;
import org.mandarin.booking.domain.venue.HallException;
import org.mandarin.booking.domain.hall.HallException;
import org.springframework.stereotype.Service;

@Service
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package org.mandarin.booking.app.venue;
package org.mandarin.booking.app.hall;

public interface HallValidator {
void checkHallExist(Long hallId);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
@NamedInterface("hall")
package org.mandarin.booking.app.hall;

import org.springframework.modulith.NamedInterface;
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

@Service
@RequiredArgsConstructor
public class AuthService implements AuthUseCase {
class AuthService implements AuthUseCase {
private final SecurePasswordEncoder securePasswordEncoder;
private final MemberQueryRepository queryRepository;
private final TokenUtils tokenUtils;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
package org.mandarin.booking.adapter.security;
package org.mandarin.booking.app.member;

import lombok.RequiredArgsConstructor;
import org.mandarin.booking.AuthException;
import org.mandarin.booking.adapter.CustomMemberAuthenticationToken;
import org.mandarin.booking.app.member.MemberQueryRepository;
import org.mandarin.booking.domain.member.Member;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.core.Authentication;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@
@Repository
@Transactional
@RequiredArgsConstructor
public class MemberCommandRepository {
class MemberCommandRepository {
private final MemberRepository jpaRepository;

public Member insert(Member member) {
Member insert(Member member) {
return jpaRepository.save(member);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,18 @@
@Repository
@Transactional(readOnly = true)
@RequiredArgsConstructor
public class MemberQueryRepository {
class MemberQueryRepository {
private final MemberRepository jpaRepository;

public boolean existsByEmail(String email) {
return jpaRepository.existsByEmail(email);
Optional<Member> findByUserId(String userId) {
return jpaRepository.findByUserId(userId);
}

public boolean existsByUserId(String userId) {
return jpaRepository.existsByUserId(userId);
boolean existsByEmail(String email) {
return jpaRepository.existsByEmail(email);
}

public Optional<Member> findByUserId(String userId) {
return jpaRepository.findByUserId(userId);
boolean existsByUserId(String userId) {
return jpaRepository.existsByUserId(userId);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

@Component
@RequiredArgsConstructor
public class MemberRegisterValidator {
class MemberRegisterValidator {
private final MemberQueryRepository queryRepository;

void checkDuplicateEmail(String email) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

@Service
@RequiredArgsConstructor
public class MemberService implements MemberRegisterer {
class MemberService implements MemberRegisterer {
private final MemberRegisterValidator validator;
private final MemberCommandRepository command;
private final SecurePasswordEncoder securePasswordEncoder;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@
@Repository
@Transactional
@RequiredArgsConstructor
public class ShowCommandRepository {
class ShowCommandRepository {
private final ShowRepository jpaRepository;

public Show insert(Show show) {
Show insert(Show show) {
return jpaRepository.save(show);
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package org.mandarin.booking.app.show;

import java.time.LocalDate;
import org.mandarin.booking.adapter.SliceView;
import org.mandarin.booking.domain.show.ShowResponse;

public interface ShowFetcher {
SliceView<ShowResponse> fetchShows(Integer page, Integer size, String type, String rating, String q,
LocalDate from, LocalDate to);
}
Loading