Skip to content

Commit

Permalink
Merge pull request #769 from woowacourse-teams/dev/be
Browse files Browse the repository at this point in the history
[BE] MySQL 대소문자 구분 문제로 태그 생성 시 다른 태그까지 생성되는 버그 픽스
  • Loading branch information
vi-wolhwa authored Oct 10, 2024
2 parents a168509 + bbafbd3 commit 2ad7598
Show file tree
Hide file tree
Showing 31 changed files with 128 additions and 71 deletions.
12 changes: 4 additions & 8 deletions backend/src/main/java/codezap/global/cors/CorsProperties.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,12 @@
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.bind.DefaultValue;

import lombok.Getter;

@Getter
@ConfigurationProperties(prefix = "cors")
public class CorsProperties {

private final String[] allowedOrigins;
private final String[] allowedOriginsPatterns;

Expand All @@ -16,12 +20,4 @@ public CorsProperties(
this.allowedOrigins = allowedOrigins;
this.allowedOriginsPatterns = allowedOriginsPatterns;
}

public String[] getAllowedOrigins() {
return allowedOrigins;
}

public String[] getAllowedOriginsPatterns() {
return allowedOriginsPatterns;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

@Getter
public class CodeZapException extends RuntimeException {

private final HttpStatusCode httpStatusCode;

public CodeZapException(HttpStatusCode httpStatusCode, String message) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ public class DataSourceRouter extends AbstractRoutingDataSource {
protected Object determineCurrentLookupKey() {
boolean readOnly = TransactionSynchronizationManager.isCurrentTransactionReadOnly();

if(readOnly) {
if (readOnly) {
return READER_KEY;
}
return WRITER_KEY;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

@Configuration
public class DateTimeFormatConfiguration {

private static final String DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss";

@Bean
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
*/
@Component
public class AuthOperationCustomizer implements OperationCustomizer {

private static final ObjectMapper objectMapper = new ObjectMapper();

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,6 @@
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface ApiErrorResponses {

ApiErrorResponse[] value();
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

@Component
public class ApiErrorResponsesCustomizer implements OperationCustomizer {

@Override
public Operation customize(Operation operation, HandlerMethod handlerMethod) {
List<ApiErrorResponse> apiErrorResponses = getApiErrorResponses(handlerMethod);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package codezap.global.validation;

public class ValidationGroups {

public interface NotNullGroup {}

public interface SourceCodeOrdinalGroup {}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import codezap.template.domain.Template;

public interface LikesRepository {

Likes save(Likes likes);

boolean existsByMemberAndTemplate(Member member, Template template);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

@Tag(name = "태그 API", description = "태그 조회 API")
public interface SpringDocTagController {

@SecurityRequirement(name = "쿠키 인증 토큰")
@Operation(summary = "태그 조회", description = "해당 멤버의 템플릿들에 포함된 태그를 조회합니다.")
@ApiResponse(responseCode = "200", description = "태그 조회 성공")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,9 @@ default Tag fetchByName(String name) {
() -> new CodeZapException(HttpStatus.NOT_FOUND, "이름이 " + name + "인 태그는 존재하지 않습니다."));
}

Optional<Tag> findByName(String name);
@Query(value = "SELECT * FROM tag WHERE tag.name = BINARY :name", nativeQuery = true)
Optional<Tag> findByName(@Param("name") String name);

@Query("select t.name from Tag t where t.name in :names")
List<String> findNameByNamesIn(@Param("names") List<String> names);
@Query(value = "SELECT * FROM tag WHERE tag.name COLLATE utf8mb4_bin IN :names", nativeQuery = true)
List<Tag> findAllByNames(@Param("names") List<String> names);
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ public interface TagRepository {

Optional<Tag> findByName(String name);

List<Tag> findByNameIn(List<String> names);
List<Tag> findAllByNames(List<String> names);

Tag save(Tag tag);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;

import codezap.tag.domain.Tag;
import codezap.template.domain.Template;
Expand All @@ -22,19 +23,19 @@ public interface TemplateTagJpaRepository extends TemplateTagRepository, JpaRepo
List<Tag> findAllTagsByTemplate(Template template);

@Query("""
SELECT tt, t
FROM TemplateTag tt
JOIN FETCH tt.tag t
WHERE tt.id.templateId = :templateId
""")
SELECT tt, t
FROM TemplateTag tt
JOIN FETCH tt.tag t
WHERE tt.id.templateId = :templateId
""")
List<TemplateTag> findAllByTemplateId(Long templateId);

@Query("""
SELECT tt, t
FROM TemplateTag tt
JOIN FETCH tt.tag t
WHERE tt.id.templateId in :templateIds
""")
SELECT tt, t
FROM TemplateTag tt
JOIN FETCH tt.tag t
WHERE tt.id.templateId in :templateIds
""")
List<TemplateTag> findAllByTemplateIdsIn(List<Long> templateIds);

@Query("""
Expand All @@ -43,13 +44,14 @@ public interface TemplateTagJpaRepository extends TemplateTagRepository, JpaRepo
WHERE t.id IN (
SELECT DISTINCT tt.id.tagId
FROM TemplateTag tt
WHERE tt.id.templateId IN
(SELECT te.id FROM Template te WHERE te.member.id = :memberId)
)
""")
WHERE tt.id.templateId IN (
SELECT te.id FROM Template te WHERE te.member.id = :memberId
)
)
""")
List<Tag> findAllTagDistinctByMemberId(Long memberId);

@Modifying(clearAutomatically = true)
@Query("DELETE FROM TemplateTag t WHERE t.template.id in :templateIds")
void deleteByTemplateIds(List<Long> templateIds);
void deleteByTemplateIds(@Param("templateIds") List<Long> templateIds);
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,6 @@ public interface TemplateTagRepository {

List<TemplateTag> findAllByTemplateId(Long templateId);

List<Long> findDistinctByTemplateIn(List<Long> templateIds);

List<TemplateTag> findAllByTemplateIdsIn(List<Long> templateIds);

TemplateTag save(TemplateTag templateTag);
Expand Down
2 changes: 1 addition & 1 deletion backend/src/main/java/codezap/tag/service/TagService.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public class TagService {

@Transactional
public void createTags(Template template, List<String> tagNames) {
List<Tag> existingTags = new ArrayList<>(tagRepository.findByNameIn(tagNames));
List<Tag> existingTags = new ArrayList<>(tagRepository.findAllByNames(tagNames));
List<String> existNames = existingTags.stream()
.map(Tag::getName)
.toList();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public interface SpringDocTemplateController {
새로운 템플릿을 생성합니다. \n
템플릿명, 템플릿 설명, 소스 코드 목록, 썸네일 순서, 카테고리 ID, 태그 목록이 필요합니다. \n
* 템플릿 이름은 비어있거나 공백일 수 없다.
소스 코드 목록은 파일명, 소스 코드, 소스 코드 순서가 필요합니다. \n
* 소스 코드 순서는 1부터 시작합니다.
* 소스 코드 순서는 오름차순으로 정렬하여 보내야 합니다.
Expand Down Expand Up @@ -62,13 +62,13 @@ public interface SpringDocTemplateController {
- 검색 키워드 (템플릿명, 템플릿 설명, 파일명, 소스 코드)
- 카테고리 ID
- 태그 ID들 \n
페이징 조건을 줄 수 있습니다. 페이지 번호는 1, 템플릿 개수는 20, 정렬 방식은 최신순이 기본 값입니다. \n
- 페이징 조건 \n
- 페이지 번호(pageNumber)
- 한 페이지에 템플릿 개수(pageSize)
- 페이지 정렬 방식(sort) \n
- 정렬 방식 \n
- 최신순 (modifiedAt,asc)
- 오래된순 (modifiedAt,desc)
Expand Down Expand Up @@ -102,13 +102,13 @@ ResponseEntity<FindAllTemplatesResponse> findAllTemplates(
- 검색 키워드 (템플릿명, 템플릿 설명, 파일명, 소스 코드)
- 카테고리 ID
- 태그 ID들 \n
페이징 조건을 줄 수 있습니다. 페이지 번호는 1, 템플릿 개수는 20, 정렬 방식은 최신순이 기본 값입니다. \n
- 페이징 조건 \n
- 페이지 번호(pageNumber)
- 한 페이지에 템플릿 개수(pageSize)
- 페이지 정렬 방식(sort) \n
- 정렬 방식 \n
- 최신순 (modifiedAt,asc)
- 오래된순 (modifiedAt,desc)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,12 @@ public ExactPhraseMatchFunction() {
}

@Override
public void render(SqlAppender sqlAppender, List<? extends SqlAstNode> arguments, ReturnableType<?> returnType, SqlAstTranslator<?> translator) {
public void render(
SqlAppender sqlAppender,
List<? extends SqlAstNode> arguments,
ReturnableType<?> returnType,
SqlAstTranslator<?> translator
) {
sqlAppender.appendSql("MATCH(");
translator.render(arguments.get(0), SqlAstNodeRenderingMode.DEFAULT);
sqlAppender.appendSql(", ");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

@SuppressWarnings("unused")
public interface SourceCodeJpaRepository extends SourceCodeRepository, JpaRepository<SourceCode, Long> {

default SourceCode fetchById(Long id) {
return findById(id).orElseThrow(
() -> new CodeZapException(HttpStatus.NOT_FOUND, "식별자 " + id + "에 해당하는 소스 코드가 존재하지 않습니다."));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import codezap.template.domain.Template;

public interface SourceCodeRepository {

SourceCode fetchById(Long id);

List<SourceCode> findAllByTemplate(Template template);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import codezap.template.domain.TemplateTag;

public class TemplateSpecification implements Specification<Template> {

private final Long memberId;
private final String keyword;
private final Long categoryId;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,11 @@ default Thumbnail fetchByTemplate(Template template) {
}

@Query("""
SELECT t, sc
FROM Thumbnail t
join fetch t.sourceCode sc
WHERE t.template = :template
""")
SELECT t, sc
FROM Thumbnail t
join fetch t.sourceCode sc
WHERE t.template = :template
""")
Optional<Thumbnail> findByTemplate(Template template);


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ class CookieCredentialManagerTest {

private MockHttpServletRequest request;
private MockHttpServletResponse response;

private CookieCredentialManager cookieCredentialManager;

@BeforeEach
Expand All @@ -34,7 +33,7 @@ void setUp() {

@Nested
@DisplayName("인증 정보 반환")
class getCredential {
class GetCredential {

@Test
@DisplayName("인증 정보 반환 성공")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@ void createCredential() {

@Nested
@DisplayName("인증 정보로부터 회원 추출")
class extractMember {
class ExtractMember {

@Test
@DisplayName("회원 추출 성공")
void extractMember() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,6 @@
import codezap.auth.dto.LoginAndCredentialDto;
import codezap.auth.dto.request.LoginRequest;
import codezap.auth.dto.response.LoginResponse;
import codezap.auth.encryption.PasswordEncryptor;
import codezap.auth.encryption.SHA2PasswordEncryptor;
import codezap.auth.provider.CredentialProvider;
import codezap.global.DatabaseIsolation;
import codezap.global.exception.CodeZapException;
Expand All @@ -29,6 +27,7 @@
@SpringBootTest
@DatabaseIsolation
public class AuthServiceTest {

@Autowired
private MemberRepository memberRepository;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ class CategoryControllerTest extends MockMvcTest {

@Nested
@DisplayName("카테고리 생성 테스트")
class createCategoryTest {
class CreateCategoryTest {

@Test
@DisplayName("카테고리 생성 성공")
Expand Down Expand Up @@ -109,7 +109,7 @@ void findAllCategoriesSuccess() throws Exception {

@Nested
@DisplayName("카테고리 수정 테스트")
class updateCategoryTest {
class UpdateCategoryTest {

@Test
@DisplayName("카테고리 수정 성공")
Expand Down Expand Up @@ -174,7 +174,7 @@ void updateCategoryFailWithDuplicatedName() throws Exception {

@Nested
@DisplayName("카테고리 삭제 테스트")
class deleteCategoryTest {
class DeleteCategoryTest {

@Test
@DisplayName("카테고리 삭제 성공")
Expand Down Expand Up @@ -205,7 +205,7 @@ void deleteCategoryFailWithUnauthorized() throws Exception {

@Test
@DisplayName("카테고리 삭제 실패: 존재하지 않는 카테고리의 삭제 요청")
void updateCategoryFailWithDuplicatedName() throws Exception {
void deleteCategoryFailWithDuplicatedName() throws Exception {
long id = 2L;

doThrow(new CodeZapException(HttpStatus.NOT_FOUND, "식별자 " + id + "에 해당하는 카테고리가 존재하지 않습니다."))
Expand All @@ -220,7 +220,7 @@ void updateCategoryFailWithDuplicatedName() throws Exception {

@Test
@DisplayName("카테고리 삭제 실패: 템플릿이 존재하는 카테고리는 삭제 불가능")
void updateCategoryFailWithlongName() throws Exception {
void deleteCategoryFailWithlongName() throws Exception {
long categoryId = 1L;
doThrow(new CodeZapException(HttpStatus.BAD_REQUEST, "템플릿이 존재하는 카테고리는 삭제할 수 없습니다."))
.when(categoryService).deleteById(any(), any());
Expand Down
Loading

0 comments on commit 2ad7598

Please sign in to comment.