Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

회원가입 약관 동의 api 수정 및 온보딩 관심 아티스트 등록 api 추가 #25

Merged
merged 15 commits into from
Jul 2, 2024
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
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
Expand Up @@ -72,18 +72,18 @@ public ResponseEntity<ArtistGetResponse> getArtist(

@GetMapping
public ResponseEntity<CursorBasePaginatedResponse<ArtistGetResponse>> getArtistList(
@RequestParam(required = false) Long cursor,
@RequestParam(defaultValue = "10") int size
@RequestParam(name = "cursor", required = false) Long cursor,
@RequestParam(name = "size", defaultValue = "10") int size
) {
return ResponseEntity
.status(HttpStatus.OK)
.body(artistQueryService.getArtistList(cursor, PageRequest.of(0, size)));
.body(artistQueryService.getArtistList(cursor, PageRequest.ofSize(size)));
}

@GetMapping("/search")
public ResponseEntity<CursorBasePaginatedResponse<ArtistGetResponse>> searchArtist(
@RequestParam(required = false) Long cursor,
@RequestParam(required = false, defaultValue = "5") int size,
@RequestParam(name = "cursor", required = false) Long cursor,
@RequestParam(name = "size", defaultValue = "10") int size,
@RequestParam String query
) {
return ResponseEntity
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,14 @@
package com.projectlyrics.server.domain.artist.dto.request;

import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.Pattern;
import jakarta.validation.constraints.NotBlank;

public record ArtistAddRequest(
@Schema(name = "아티스트의 한글 이름")
@Pattern(regexp = "^(?!\\s*$).+", message = "빈 문자열 또는 공백 문자열은 허용하지 않습니다.")
@NotBlank
@Schema(name = "아티스트의 이름")
String name,
@Schema(name = "아티스트의 영어 이름")
@Pattern(regexp = "^(?!\\s*$).+", message = "빈 문자열 또는 공백 문자열은 허용하지 않습니다.")
String englishName,

@Schema(name = "아티스트의 cdn 이미지 경로")
@Pattern(regexp = "^https://.*", message = "이미지 경로는 https://로 시작해야 합니다.")
String profileImageCdnLink
String imageUrl
) {
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,7 @@
public record ArtistUpdateRequest(
@Schema(name = "아티스트의 한글 이름")
String name,
@Schema(name = "아티스트의 영어 이름")
String englishName,
@Schema(name = "아티스트의 cdn 이미지 경로")

String profileImageCdnLink
) {
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,14 @@
public record ArtistGetResponse(
Long id,
String name,
String englishName,
String profileImageCdnLink
String imageUrl
) implements CursorResponse {

public static ArtistGetResponse of(Artist artist) {
return new ArtistGetResponse(
artist.getId(),
artist.getName(),
artist.getEnglishName(),
artist.getProfileImageCdnLink()
artist.getImageUrl()
);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,14 @@
public record ArtistUpdateResponse(
Long id,
String name,
String englishName,
String profileImageCdnLink
) {

public static ArtistUpdateResponse from(Artist artist) {
return new ArtistUpdateResponse(
artist.getId(),
artist.getName(),
artist.getEnglishName(),
artist.getProfileImageCdnLink()
artist.getImageUrl()
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import jakarta.persistence.Id;
import jakarta.persistence.Table;

import java.util.Optional;
import java.util.function.Consumer;

import lombok.*;
Expand All @@ -29,45 +30,39 @@ public class Artist extends BaseEntity {
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@Column(nullable = true)
@Column(nullable = false)
private String name;

@Column(nullable = true)
private String englishName;
@Column
private String imageUrl;

@Column(nullable = true)
private String profileImageCdnLink;
public static Artist of(String name, String imageUrl) {
return new Artist(name, imageUrl);
}

public static Artist from(ArtistAddRequest dto) {
checkString(dto.name());
checkString(dto.englishName());
checkUrl(dto.profileImageCdnLink());

return new Artist(
dto.name(),
dto.englishName(),
dto.profileImageCdnLink()
dto.imageUrl()
);
}

private Artist(String name, String englishName, String profileImageCdnLink) {
private Artist(String name, String imageUrl) {
checkString(name);
Optional.ofNullable(imageUrl)
.ifPresent(DomainUtils::checkUrl);
Comment on lines +52 to +53
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이 부분과 DTO 쪽 읽고 알게 된 건데, 아티스트 이미지가 없는 경우도 허용되는 걸까요?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이미지같은 경우는 데이터를 어떤 식으로 저장하게 될지 모르기도 하고 추후에 애플리케이션이 좀 성숙해졌을 때 결정할 일인 것 같아서 우선 null 값이 들어가도 되도록 구현해놨습니다.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

네 이해했습니다 감사합니다!!

this.name = name;
this.englishName = englishName;
this.profileImageCdnLink = profileImageCdnLink;
this.imageUrl = imageUrl;
}

public void updateName(String name) {
this.name = name;
}

public void updateEnglishName(String englishName) {
this.englishName = englishName;
}

public void updateProfileImageCdnLink(String profileImageCdnLink) {
DomainUtils.checkUrl(profileImageCdnLink);
public void updateImageUrl(String imageUrl) {
DomainUtils.checkUrl(imageUrl);

this.profileImageCdnLink = profileImageCdnLink;
this.imageUrl = imageUrl;
}

public void updateIfNotBlank(String value, Consumer<String> updater) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.projectlyrics.server.domain.artist.entity.Artist;

import java.util.List;
import java.util.Optional;

import org.springframework.data.domain.Pageable;
Expand All @@ -14,4 +15,6 @@ public interface ArtistQueryRepository {
Slice<Artist> findAllByQueryAndNotDeleted(String query, Long cursor, Pageable pageable);

Slice<Artist> findAllAndNotDeleted(Long cursor, Pageable pageable);

List<Artist> findAllByIds(List<Long> artistIds);
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ public Slice<Artist> findAllAndNotDeleted(Long cursor, Pageable pageable) {
List<Artist> content = jpaQueryFactory
.selectFrom(QArtist.artist)
.where(
goeCursorId(cursor),
QueryDslUtils.gtCursorId(cursor, QArtist.artist.id),
QArtist.artist.deletedAt.isNull()
)
.limit(pageable.getPageSize() + 1)
Expand All @@ -50,24 +50,30 @@ public Slice<Artist> findAllAndNotDeleted(Long cursor, Pageable pageable) {
return new SliceImpl<>(content, pageable, QueryDslUtils.checkIfHasNext(pageable, content));
}

@Override
public List<Artist> findAllByIds(List<Long> artistIds) {
return jpaQueryFactory.selectFrom(QArtist.artist)
.where(
QArtist.artist.id.in(artistIds),
QArtist.artist.deletedAt.isNull()
)
.fetch();
}

@Override
public Slice<Artist> findAllByQueryAndNotDeleted(String query, Long cursor, Pageable pageable) {
List<Artist> content = jpaQueryFactory
.selectFrom(QArtist.artist)
.where(
goeCursorId(cursor),
QueryDslUtils.gtCursorId(cursor, QArtist.artist.id),
QArtist.artist.deletedAt.isNull(),
anyOf(
QArtist.artist.name.contains(query),
QArtist.artist.englishName.contains(query))
QArtist.artist.name.contains(query)
)
)
.limit(pageable.getPageSize() + 1)
.fetch();

return new SliceImpl<>(content, pageable, QueryDslUtils.checkIfHasNext(pageable, content));
}

private BooleanExpression goeCursorId(Long cursor) {
return cursor == null ? null : QArtist.artist.id.goe(cursor);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,7 @@ public ArtistUpdateResponse updateArtist(Long artistId, ArtistUpdateRequest requ
.orElseThrow(ArtistNotFoundException::new);

artist.updateIfNotBlank(request.name(), artist::updateName);
artist.updateIfNotBlank(request.englishName(), artist::updateEnglishName);
artist.updateIfNotBlank(request.profileImageCdnLink(), artist::updateProfileImageCdnLink);
artist.updateIfNotBlank(request.profileImageCdnLink(), artist::updateImageUrl);

return ArtistUpdateResponse.from(artist);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

@RequiredArgsConstructor
@Transactional(readOnly = true)
@Service
Expand Down Expand Up @@ -40,4 +42,8 @@ public CursorBasePaginatedResponse<ArtistGetResponse> searchArtists(String query

return CursorBasePaginatedResponse.of(searchedArtists);
}

public List<Artist> getArtistsByIds(List<Long> artistIds) {
return artistQueryRepository.findAllByIds(artistIds);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,12 @@
import jakarta.servlet.http.HttpServletResponse;

import java.io.IOException;
import java.util.Arrays;
import java.util.Optional;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.stereotype.Component;
Expand All @@ -31,21 +33,26 @@ public class JwtAuthenticationFilter extends OncePerRequestFilter {

private static final String TOKEN_PREFIX = "Bearer ";

@Value("#{'${auth.free-apis}'.split(',')}")
private String[] excludePath;

private final JwtTokenProvider jwtTokenProvider;

@Override
protected boolean shouldNotFilter(HttpServletRequest request) throws ServletException {
String path = request.getRequestURI();
return Arrays.asList(excludePath).contains(path);
}

Comment on lines +41 to +46
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

결국 이 부분을 넣으셨군요 ㅎㅎㅎ...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

exceptionHandler 방식과 requestMatchers("/api/**").authenticated() 을 동시에 사용하는 경우에는 이 방법 외에는 해결할 방법이 잘 보이지 않더라구요..ㅎㅎ

@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
try {
String token = getAccessTokenFromRequest(request);

validateToken(token);
setUserIntoContext(token, request);
} catch (RuntimeException e) {
log.debug(e.getMessage());
} finally {
filterChain.doFilter(request, response);
}
String token = getAccessTokenFromRequest(request);

validateToken(token);

setUserIntoContext(token, request);
filterChain.doFilter(request, response);
}

private String getAccessTokenFromRequest(HttpServletRequest request) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import org.springframework.format.annotation.DateTimeFormat;

import java.time.Year;
import java.util.List;

public record AuthSignUpRequest(
@NotBlank
Expand All @@ -33,7 +34,7 @@ public record AuthSignUpRequest(
Year birthYear,

@Valid
TermsInput terms
List<TermsInput> terms
) {

public record TermsInput(
Expand All @@ -42,8 +43,11 @@ public record TermsInput(
boolean agree,

@NotNull
@Schema(description = "약관 내용")
@Schema(description = "약관 제목")
String title,

String agreement) {
@Schema(description = "약관 내용 링크")
String agreement
) {
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -82,14 +82,14 @@ public JwtValidationType validateToken(String token) {
Claims claims = getBody(token);

return VALID_JWT;
} catch (MalformedJwtException ex) {
return INVALID_JWT_TOKEN;
} catch (ExpiredJwtException ex) {
return EXPIRED_JWT_TOKEN;
} catch (UnsupportedJwtException ex) {
return UNSUPPORTED_JWT_TOKEN;
} catch (IllegalArgumentException ex) {
return EMPTY_JWT;
} catch (Exception ex) {
return INVALID_JWT_TOKEN;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,14 @@
import org.springframework.data.domain.Slice;

public record CursorBasePaginatedResponse<T>(
@Schema(description = "다음 페이지를 요청하기 위한 커서 값") boolean hasNext,
@Schema(description = "다음 페이지를 요청하기 위한 커서 값") Long nextCursor,
@Schema(description = "다음 페이지 존재 여부") boolean hasNext,
@Schema(description = "요청한 데이터") List<T> data
) {

public static <T> CursorBasePaginatedResponse<T> of(Slice<T> slice) {
public static <T extends CursorResponse> CursorBasePaginatedResponse<T> of(Slice<T> slice) {
return new CursorBasePaginatedResponse<>(
slice.getContent().isEmpty() ? null : slice.getContent().getLast().getId(),
Comment on lines +15 to +17
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CursorResponse 여기서도 사용하기 좋은 것 같네요!

slice.hasNext(),
slice.getContent()
);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
package com.projectlyrics.server.domain.common.util;

import com.projectlyrics.server.domain.artist.entity.QArtist;
import com.querydsl.core.types.dsl.BooleanExpression;

import java.util.List;

import com.querydsl.core.types.dsl.NumberPath;
import org.springframework.data.domain.Pageable;

public class QueryDslUtils {

public static BooleanExpression goeCursorId(Long cursor) {
return cursor == null ? null : QArtist.artist.id.goe(cursor);
public static BooleanExpression gtCursorId(Long cursor, NumberPath<Long> id) {
return cursor == null ? null : id.gt(cursor);
Comment on lines +12 to +13
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

혹시 goe에서 gt로 가게 되면서 버그가 날 수 있는 부분은 없을까요?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cursor값이 어떻게 들어오냐에 따라 달라질 수 있을 것 같네요
저번 리팩터링에서 nextCursor을 주는 방식을 바꿨기 때문에 현재로는 goe가 들어오면 버그가 발생합니다 🙂

}

public static <T> boolean checkIfHasNext(Pageable pageable, List<T> content) {
Expand Down
Loading
Loading