Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
6 changes: 6 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,12 @@ dependencies {
implementation 'com.github.loki4j:loki-logback-appender:1.4.1'
implementation "org.springframework.boot:spring-boot-starter-actuator"
runtimeOnly "io.micrometer:micrometer-registry-prometheus"

// Bad Word Filtering
implementation 'io.github.vaneproject:badwordfiltering:1.0.0'

// Mail
implementation 'org.springframework.boot:spring-boot-starter-mail'
}

tasks.named('test') {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
import io.jsonwebtoken.JwtException;
import io.jsonwebtoken.MalformedJwtException;
import lombok.RequiredArgsConstructor;
import org.fontory.fontorybe.authentication.domain.exception.InvalidRefreshTokenException;
import org.fontory.fontorybe.authentication.domain.exception.TokenNotFoundException;
import org.fontory.fontorybe.bookmark.domain.exception.BookmarkAlreadyException;
import org.fontory.fontorybe.bookmark.domain.exception.BookmarkNotFoundException;
import org.fontory.fontorybe.common.domain.BaseErrorResponse;
Expand All @@ -12,14 +14,19 @@
import org.fontory.fontorybe.file.domain.exception.FileNotFoundException;
import org.fontory.fontorybe.file.domain.exception.InvalidMultipartRequestException;
import org.fontory.fontorybe.file.domain.exception.SingleFileRequiredException;
import org.fontory.fontorybe.font.domain.exception.FontContainsBadWordException;
import org.fontory.fontorybe.font.domain.exception.FontDuplicateNameExistsException;
import org.fontory.fontorybe.font.domain.exception.FontInvalidStatusException;
import org.fontory.fontorybe.font.domain.exception.FontNotFoundException;
import org.fontory.fontorybe.font.domain.exception.FontOwnerMismatchException;
import org.fontory.fontorybe.font.domain.exception.FontSQSProduceExcepetion;
import org.fontory.fontorybe.member.domain.exception.*;
import org.fontory.fontorybe.authentication.domain.exception.InvalidRefreshTokenException;
import org.fontory.fontorybe.authentication.domain.exception.TokenNotFoundException;
import org.fontory.fontorybe.member.domain.exception.MemberAlreadyDisabledException;
import org.fontory.fontorybe.member.domain.exception.MemberAlreadyExistException;
import org.fontory.fontorybe.member.domain.exception.MemberAlreadyJoinedException;
import org.fontory.fontorybe.member.domain.exception.MemberContainsBadWordException;
import org.fontory.fontorybe.member.domain.exception.MemberDuplicateNameExistsException;
import org.fontory.fontorybe.member.domain.exception.MemberNotFoundException;
import org.fontory.fontorybe.member.domain.exception.MemberOwnerMismatchException;
import org.fontory.fontorybe.provide.domain.exception.ProvideNotFoundException;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ExceptionHandler;
Expand Down Expand Up @@ -156,4 +163,10 @@ public BaseErrorResponse fontInvalidStatusException(FontInvalidStatusException e
public BaseErrorResponse fileNotFoundException(FileNotFoundException e) {
return new BaseErrorResponse(e.getMessage());
}

@ResponseStatus(HttpStatus.BAD_REQUEST)
@ExceptionHandler({FontContainsBadWordException.class, MemberContainsBadWordException.class})
public BaseErrorResponse containsBadWordException(Exception e) {
return new BaseErrorResponse(e.getMessage());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package org.fontory.fontorybe.config;

import com.vane.badwordfiltering.BadWordFiltering;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class BadWordFilteringConfig {

@Bean
public BadWordFiltering badWordFiltering() {
return new BadWordFiltering();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package org.fontory.fontorybe.font.domain.exception;

import org.fontory.fontorybe.common.domain.SkipDiscordNotification;

@SkipDiscordNotification
public class FontContainsBadWordException extends RuntimeException {
public FontContainsBadWordException() {
super("Font contains bad word");
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.fontory.fontorybe.font.service;

import com.vane.badwordfiltering.BadWordFiltering;
import java.util.List;
import java.util.stream.Collectors;
import lombok.RequiredArgsConstructor;
Expand All @@ -9,9 +10,18 @@
import org.fontory.fontorybe.file.application.port.FileService;
import org.fontory.fontorybe.file.domain.FileMetadata;
import org.fontory.fontorybe.file.domain.FileUploadResult;
import org.fontory.fontorybe.font.controller.dto.*;
import org.fontory.fontorybe.font.controller.dto.FontCreateDTO;
import org.fontory.fontorybe.font.controller.dto.FontDeleteResponse;
import org.fontory.fontorybe.font.controller.dto.FontDownloadResponse;
import org.fontory.fontorybe.font.controller.dto.FontPageResponse;
import org.fontory.fontorybe.font.controller.dto.FontProgressResponse;
import org.fontory.fontorybe.font.controller.dto.FontProgressUpdateDTO;
import org.fontory.fontorybe.font.controller.dto.FontResponse;
import org.fontory.fontorybe.font.controller.dto.FontUpdateDTO;
import org.fontory.fontorybe.font.controller.dto.FontUpdateResponse;
import org.fontory.fontorybe.font.controller.port.FontService;
import org.fontory.fontorybe.font.domain.Font;
import org.fontory.fontorybe.font.domain.exception.FontContainsBadWordException;
import org.fontory.fontorybe.font.domain.exception.FontDuplicateNameExistsException;
import org.fontory.fontorybe.font.domain.exception.FontInvalidStatusException;
import org.fontory.fontorybe.font.domain.exception.FontNotFoundException;
Expand Down Expand Up @@ -39,6 +49,7 @@ public class FontServiceImpl implements FontService {
private final MemberLookupService memberLookupService;
private final FontRequestProducer fontRequestProducer;
private final CloudStorageService cloudStorageService;
private final BadWordFiltering badWordFiltering;

@Override
@Transactional
Expand All @@ -49,6 +60,9 @@ public Font create(Long memberId, FontCreateDTO fontCreateDTO, FileUploadResult
if (isDuplicateNameExists(memberId, fontCreateDTO.getName())) {
throw new FontDuplicateNameExistsException();
}

checkContainsBadWord(fontCreateDTO.getName(), fontCreateDTO.getExample());

FileMetadata fileMetadata = fileService.getOrThrowById(fileDetails.getId());

Font savedFont = fontRepository.save(Font.from(fontCreateDTO, member.getId(), fileMetadata.getKey()));
Expand Down Expand Up @@ -82,6 +96,7 @@ public FontUpdateResponse update(Long memberId, Long fontId, FontUpdateDTO fontU
Font targetFont = getOrThrowById(fontId);

checkFontOwnership(member.getId(), targetFont.getMemberId());
checkContainsBadWord(fontUpdateDTO.getName(), fontUpdateDTO.getExample());

Font updatedFont = fontRepository.save(targetFont.update(fontUpdateDTO));
String woff2Url = cloudStorageService.getWoff2Url(updatedFont.getKey());
Expand Down Expand Up @@ -340,4 +355,13 @@ private void checkFontStatusIsDone(Font targetFont) {
throw new FontInvalidStatusException();
}
}

private void checkContainsBadWord(String name, String example) {
log.debug("Service detail: Checking bad word: name={}, example={}", name, example);

if (badWordFiltering.blankCheck(name) || badWordFiltering.blankCheck(example)) {
log.warn("Service warning: Font contains bad word: name={}, example={}", name, example);
throw new FontContainsBadWordException();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package org.fontory.fontorybe.member.domain.exception;

import org.fontory.fontorybe.common.domain.SkipDiscordNotification;

@SkipDiscordNotification
public class MemberContainsBadWordException extends RuntimeException {
public MemberContainsBadWordException() {
super("Member contains bad word.");
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.fontory.fontorybe.member.service;

import com.vane.badwordfiltering.BadWordFiltering;
import lombok.Builder;
import lombok.RequiredArgsConstructor;
import org.fontory.fontorybe.file.application.port.FileService;
Expand All @@ -11,6 +12,7 @@
import org.fontory.fontorybe.member.controller.port.MemberOnboardService;
import org.fontory.fontorybe.member.domain.Member;
import org.fontory.fontorybe.member.domain.exception.MemberAlreadyJoinedException;
import org.fontory.fontorybe.member.domain.exception.MemberContainsBadWordException;
import org.fontory.fontorybe.member.domain.exception.MemberDuplicateNameExistsException;
import org.fontory.fontorybe.member.infrastructure.entity.MemberStatus;
import org.fontory.fontorybe.member.service.port.MemberRepository;
Expand All @@ -26,6 +28,7 @@ public class MemberOnboardServiceImpl implements MemberOnboardService {
private final MemberLookupService memberLookupService;
private final MemberCreationService memberCreationService;
private final FileService fileService;
private final BadWordFiltering badWordFiltering;

@Override
@Transactional
Expand All @@ -50,6 +53,14 @@ public Member initNewMemberInfo(Long requestMemberId,
throw new MemberDuplicateNameExistsException();
}

checkContainsBadWord(initNewMemberInfoRequest.getNickname());

return memberRepository.save(targetMember.initNewMemberInfo(initNewMemberInfoRequest, fileMetadata.getKey()));
}

private void checkContainsBadWord(String nickname) {
if (badWordFiltering.blankCheck(nickname)) {
throw new MemberContainsBadWordException();
}
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.fontory.fontorybe.member.service;

import com.vane.badwordfiltering.BadWordFiltering;
import lombok.Builder;
import lombok.RequiredArgsConstructor;
import org.fontory.fontorybe.authentication.application.port.JwtTokenProvider;
Expand All @@ -8,6 +9,7 @@
import org.fontory.fontorybe.member.domain.Member;
import org.fontory.fontorybe.member.controller.dto.MemberUpdateRequest;
import org.fontory.fontorybe.member.domain.exception.MemberAlreadyDisabledException;
import org.fontory.fontorybe.member.domain.exception.MemberContainsBadWordException;
import org.fontory.fontorybe.member.domain.exception.MemberDuplicateNameExistsException;
import org.fontory.fontorybe.member.service.port.MemberRepository;
import org.fontory.fontorybe.provide.controller.port.ProvideService;
Expand All @@ -23,6 +25,7 @@ public class MemberUpdateServiceImpl implements MemberUpdateService {
private final JwtTokenProvider jwtTokenProvider;
private final MemberRepository memberRepository;
private final ProvideService provideService;
private final BadWordFiltering badWordFiltering;

@Override
@Transactional
Expand All @@ -34,6 +37,8 @@ public Member update(Long requestMemberId, MemberUpdateRequest memberUpdateReque
throw new MemberDuplicateNameExistsException();
}

checkContainsBadWord(memberUpdateRequest.getNickname());

return memberRepository.save(targetMember.update(memberUpdateRequest));
}

Expand All @@ -56,4 +61,10 @@ public Member disable(Long requestMemberId) {

return memberRepository.save(targetMember);
}

private void checkContainsBadWord(String nickname) {
if (badWordFiltering.blankCheck(nickname)) {
throw new MemberContainsBadWordException();
}
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.fontory.fontorybe.unit.mock;

import com.vane.badwordfiltering.BadWordFiltering;
import org.fontory.fontorybe.authentication.adapter.outbound.CookieUtilsImpl;
import org.fontory.fontorybe.config.S3Config;
import org.fontory.fontorybe.config.jwt.JwtProperties;
Expand Down Expand Up @@ -82,6 +83,7 @@ public class TestContainer {
public final MemberDefaults memberDefaults;
public final CookieUtils cookieUtils;
public final S3Config s3Config;
public final BadWordFiltering badWordFiltering;

public TestContainer() {
props = new JwtProperties(
Expand All @@ -105,6 +107,8 @@ public TestContainer() {

tokenStorage = new RedisTokenStorage(fakeRedisTemplate, props);

badWordFiltering = new BadWordFiltering();

s3Config = new S3Config(
TEST_AWS_REGION,
TEST_CDN_URL,
Expand All @@ -130,6 +134,7 @@ public TestContainer() {
.memberRepository(memberRepository)
.provideService(provideService)
.jwtTokenProvider(jwtTokenProvider)
.badWordFiltering(badWordFiltering)
.build();

memberDefaults = new MemberDefaults(
Expand Down Expand Up @@ -166,6 +171,7 @@ public TestContainer() {
.memberRepository(memberRepository)
.memberLookupService(memberLookupService)
.memberCreationService(memberCreationService)
.badWordFiltering(badWordFiltering)
.build();

memberController = MemberController.builder()
Expand Down
Loading